gpt4 book ai didi

algorithm - bool 网格的随机索引

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:55:13 25 4
gpt4 key购买 nike

假设我有一个正方形 boolean grid (二维数组)大小为 N .一些值是 true有些是false (<true values> / <false values> 比率未指定)。我想随机选择一个指数 (x, y)这样grid[x][y]true .如果我想要一个省时的解决方案,我会做这样的事情(Python):

x, y = random.choice([(x, y) for x in range(N) for y in range(N) if grid[x][y]])

但这是 O(N^2) ,这对于 tic-tac-toe 游戏的实现来说已经绰绰有余了,但我猜想对于大 N 来说它会消耗更多的内存。 .

如果我想要一些不占用内存的东西,我会这样做:

x, y = 0, 0
t = N - 1
while True:
x = random.randint(0, t)
y = random.randint(0, t)
if grid[x][y]:
break

但问题是,如果我有一个大小为 10^4 的网格而且只有一两个true中的值,可能需要永远“猜测”哪个指数是我感兴趣的指数。我应该如何使这个算法最优?

最佳答案

如果网格是静态的或变化不大,或者您有时间进行一些预处理,您可以存储一个数组,其中包含每行真值的数量、真值的总数以及一个列表非零行(如果网格发生变化,您可以随时更新所有这些行):

grid        per row

0 1 0 0 1 0 2
0 0 0 0 0 0 0
0 0 1 0 0 0 1
0 0 0 0 1 0 1
0 0 0 0 0 0 0
1 0 1 1 1 0 4
total = 8

non-zero rows: [0, 2, 3, 5]

要选择一个随机索引,选择一个随机值 r 直到真值的总数,用每个非零行的真值数遍历数组,将它们相加直到你知道 r-第 r 个真值在中,然后遍历该行以找到第 r 个真值的位置。

(您可以简单地先选择一个非空行,然后从该行中选择一个真值,但这会产生不均匀的概率。)

对于 N×N 大小的网格,预处理将花费 N×N 时间和 2×N 空间,但最坏情况下的查找时间为 N。在实践中,使用下面的 JavaScript 代码示例,预处理和查找时间(以毫秒为单位)的顺序为:

  grid size      pre-processing    look-up  
10000 x 10000 5000 2.2
1000 x 1000 50 0.22
100 x 100 0.5 0.022

如您所见,对于大型网格,查找比预处理快 2000 多倍,因此如果您需要在同一(或略微改变的)网格上随机选择多个位置,预处理会很有道理。

function random2D(grid) {
this.grid = grid;
this.num = this.grid.map(function(elem) { // number of true values per row
return elem.reduce(function(sum, val) {
return sum + (val ? 1 : 0);
}, 0);
});
this.total = this.num.reduce(function(sum, val) { // total number of true values
return sum + val;
}, 0);

this.update = function(row, col, val) { // change value in grid
var prev = this.grid[row][col];
this.grid[row][col] = val;
if (prev ^ val) {
this.num[row] += val ? 1 : -1;
this.total += val ? 1 : -1;
}
}

this.select = function() { // select random index
var row = 0, col = 0;
var rnd = Math.floor(Math.random() * this.total) + 1;
while (rnd > this.num[row]) { // find row
rnd -= this.num[row++];
}
while (rnd) { // find column
if (this.grid[row][col]) --rnd;
if (rnd) ++col;
}
return {x: col, y: row};
}
}

var grid = [], size = 1000, prob = 0.01; // generate test data
for (var i = 0; i < size; i++) {
grid[i] = [];
for (var j = 0; j < size; j++) {
grid[i][j] = Math.random() < prob;
}
}
var rnd = new random2D(grid); // pre-process grid
document.write(JSON.stringify(rnd.select())); // get random index

保留包含至少一个真值的行的列表只对非常稀疏填充的网格有意义,其中许多行不包含真值,所以我没有在代码示例中实现它。如果您实现它,非常稀疏数组的查找时间将减少到不到 1µs。

关于algorithm - bool 网格的随机索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39178919/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com