我正在尝试制作一个5x5表,其中数字1-5随机放入行/列。但是他们需要为每一行和每列提供所有不同的数字。
例如: 12345 54123 41532 35214 23451
我目前的代码很长,所以我会给它一个pastebin链接。 http://pastebin.com/ex1bcLxh
任何和所有帮助将不胜感激。
答案 0 :(得分:2)
订单5减少Latin squares 56,枚举here。 “减少”意味着它们中的每一个都按排序顺序具有顶行和最左列。
您可以将任何排列应用于拉丁方的行或列, 结果也将是拉丁方。此外,任何拉丁方都可以通过以下方式转换为简化的拉丁方:
(左上角元素在第一次排列后已经处于正确位置,因此在第二步中只有n-1行而不是n行进行排序。)
因此,通过颠倒这个操作,我们可以从56个缩小的拉丁方格中的一个开始, 并生成任意代表完整集的56 *(5!)*(4!)= 161280个方块。
所以:
假设在步骤1-3中均匀分布的样本,这个过程应该从161280个5阶拉丁方的整套中得到均匀分布的样本。
答案 1 :(得分:1)
这就是我从头脑中想出来的东西 - 我没有对优化感到困扰,因为问题中提到的5x5网格大小让人感觉很快。 (在IE7中测试甚至7x7网格只需要几秒钟.8x8明显更慢,有时足够慢以触发长时间运行的脚本错误。)
function createGrid(size) {
var grid = [],
row = [],
x,y,t;
for (x=size; x>0; x--)
row.push(x);
addRows:
while (grid.length < size) {
t = row.slice();
row = [];
while (t.length > 0)
row.push(t.splice(Math.floor(Math.random() * t.length), 1)[0]);
for (y=0; y<grid.length; y++)
for (x=0; x<size; x++)
if (row[x] === grid[y][x])
continue addRows;
grid.push(row);
}
return grid;
}
var test = createGrid(5);
alert(test.join("\n"));
如果不明显,基本想法是从一行[5,4,3,2,1]开始;洗牌并检查是否可以添加;重复直到完成。
(我想通过生成所有可能的行然后从它们中随机选择开始,但考虑到我对排列算法不是很好,这似乎太麻烦了 - 每次进行随机随机播放似乎要少得多麻烦。)
答案 2 :(得分:0)
一般来说,这是一项艰巨的任务,特别是如果您担心在所有拉丁方格中均匀分布。 (至少有one book完全专注于这个主题。)这里是一种算法的伪代码(不是最有效的,但会完成工作):
for each row {
make an array of the integers 1..N
repeat {
make a random permutation of the array
} while (array conficts with any previously assigned row)
set row to array
}
(数组a
与行r
“冲突”,如果行中的某些i为a[i] == r[i]
。)这假设您有代码随机调整数组。如果您没有方便的随机播放算法,请在网上搜索。
答案 3 :(得分:0)
正如Ted Hopp所指出的,这也称为Latin Square。
拉丁方是一类exact cover问题,因此可以使用Knuth's Algorithm X找到解决方案。
Dancing Links表示不应该太难以在Javascript中编码。我在Lua中实现了类似的东西。
术语可能令人困惑,因为算法描述指的是&#34;矩阵&#34;,&#34;行&#34;和&#34;列&#34;但是这些与(输出)矩阵的行和列不同。相反,&#34;行&#34;是数组中的候选条目(a[1][2]=3
等)和&#34;列&#34;是一种模式,其中一个坐标或值是通配符,例如a[Y][2]=3
,a[1][X]=3
,a[1][2]=V
。
要选择随机解决方案,您可以在将条目列表分配到&#34;行之前随机随机播放条目列表。算法。 (在Dancing Links表示的情况下,行形成循环链接列表,您可以按随机顺序将条目插入此列表。)