如何生成一个带有值的二维数组,每个值都有不同、不重复值的邻居?

How do I generate a 2D Array with values, each with neighbours of different, non-repeating values?

提问人:jordan 提问时间:8/23/2022 最后编辑:jordan 更新时间:8/24/2022 访问量:232

问:

我有一个方形的 2D 数组,我希望用 1 到 4 之间的值填充它。 为了正确起见,数组中任何值的邻居都需要如下所示,例如:

x 2 x
3 1 1
x 4 x

x 值与中间值 1 无关。正如我们所看到的,中间值 1 的邻居除了它自己之外,不会出现超过一次

不正确值的邻居将如下所示:

x 2 x
3 1 2
x 4 x

中间值 1 的邻居之一出现不止一次(值 2 出现两次),我们不希望出现这种情况。

我已经为这个问题制定了一个 LUA 解决方案,但它非常慢,因为它所做的只是在生成中添加 2 个规则并运行所有组合,直到找到有效的组合。

规则是:

  1. 角邻居(在我们的例子中是 xs)不能与中间值具有相同的值
  2. 相关邻居的下一个值不能与中间值具有相同的值。 对规则2的解释:
y y y y
y 1 y x
y y y y

此实例中的 x 的值不能为 1,这适用于每个垂直和水平方向(上-下-左-右)

编辑:我现在知道我可以重复一个可平铺的模式,但这不是我想要的,因为我不希望观察到清晰的重复

数组 算法 语言无关

评论

0赞 IVlad 8/23/2022
对于更大的阵列,比如 6x6,这将如何寻找?
0赞 jordan 8/23/2022
6x6 的正确解决方案如下所示:1 3 4 1 3 3 4 3 2 1 4 2 4 1 2 3 4 1 2 1 4 3 2 1 2 3 4 1 2 4 4 3 2 1 3 4

答:

0赞 MangoNrFive 8/23/2022 #1

您可以使用一个 Block,如果在任何方向上重复任意次数,则不会破坏邻里约束。一个这样的块(我敢肯定还有其他块,但我认为这是最微不足道的块)将是:

1 1 2 2
3 3 4 4
2 2 1 1
4 4 3 3

您可以在任何方向上重复此块任意次数,并且每个单元格将始终具有唯一的邻居。

例如,如果你需要一个 6x8 数组,只需向右和向下重复一次 Block,然后根据你想要的大小进行切片:

1 1 2 2  1 1
3 3 4 4  3 3
2 2 1 1  2 2
4 4 3 3  4 4

1 1 2 2  1 1
3 3 4 4  3 3
2 2 1 1  2 2
4 4 3 3  4 4

有趣的事实:在进一步的检查中,人们可能会意识到,Abhinav Mathur和我提出了一个有点类似的解决方案。如果你旋转我的方块并将 2 换成 3,模式是相同的。但是,在大多数情况下,他用重复行而不是整个块的公式可能更容易实现。

1赞 Abhinav Mathur 8/23/2022 #2

您可以简单地重复一个模式来获得所需的数组。

  1. 第 1 行:重复所需的列数1 2 3 4 1 2 3...
  2. 第 2 行:以类似方式重复3 4 1 2 3 4 1...
  3. 第 3 行:与第 2 行相同
  4. 第 4 行:与第 1 行相同
  5. 第 5 行:从第 1 行开始重复模式

...继续所需的行数。

下面是 6x6 网格的示例:

1 2 3 4 1 2
3 4 1 2 3 4
3 4 1 2 3 4
1 2 3 4 1 2
1 2 3 4 1 2
3 4 1 2 3 4

这保证遵循这两个规则,因为:

  1. 值 here 的对角线将始终为 ,而 对于 。x5 - xx != (5 - x)x in [1,2,3,4]
  2. 下一个 over 值 for 将始终为 ,反之亦然(在任何方向上),并且 for 和 相同。1324

编辑:在您的评论中,您提到您需要数组更加“多样化”。任何形式的随机性都意味着我们不能使用任何模式。在这种情况下,您当前的解决方案无法改进,因为您不能使用任何模式进行优化。

评论

0赞 jordan 8/23/2022
谢谢你的回答!是的,你重复一个模式是对的,但是我希望这个数组更加多样化,因为我要用它来生成某种映射,并且让它清楚地一遍又一遍地重复并不是我真正想要的。很抱歉我没有在帖子中澄清这一点。
0赞 Abhinav Mathur 8/24/2022
@jordan编辑了答案,以包含对“多样性”约束的注释。
0赞 MangoNrFive 8/24/2022 #3

我写这个作为第二个答案,因为有一个新的要求:不要使用任何重复模式!

顶级域名

只需从左到右逐行填写数组。具有以下约束条件:

enter image description here

您要填充值 x,然后只需考虑彩色单元格中的值。

  1. 如果绿色单元格被填充,则 x 只有一种可能性(绿色或红色单元格中都不存在的一个值)
  2. 如果绿色单元格为空(您位于左边框)。然后有两个选项(其中一个值不在红色单元格中)。但是您选择的值也必须是蓝色单元格中的值之一(这始终是可能的),否则以后将无法填充值 y!如果蓝色单元格未填充(右边框),则可以忽略此辅助约束。

解释

您可以将其分为两个独立的问题。把你的数组想象成一个棋盘,分别求解明场和暗场中的数字,因为它们彼此不关心(明和暗不共享任何邻居,因为它们的邻居总是分别具有相反的颜色)。

所以你把你的棋盘分成明暗两色(只是为了更好地理解,你不必真正分开数组)。

enter image description here

然后,使用一些简单的约束分别解决它们。该值(绿色)不允许等于相隔两个单元格的值之一(红色):

enter image description here

只需从左到右逐行填写值即可。实际上,您只能在左边框处选择一个值,因为其余值将受到上述其他三个值的约束。在这个左边边界,你必须小心。绿色单元格中选择的值必须与蓝色单元格中的值之一相同。否则,下一个单元格(红色)将是不可能的!

enter image description here

只需对浅色和深色单元格执行此操作,然后将它们重新组合在一起:

enter image description here

这应该相对容易实现并且非常快,因为它不是暴力破解,而是直接构建一个有效的解决方案。当说选择一个数字或填充值时,我的意思是只获取可能的值并随机选择一个。

您也可以在excel中尝试自己,这就像一个非常无聊的数独,因为实际上没有太多选择,它真的很受限制:)。

评论

0赞 jordan 8/24/2022
谢谢你的这个伟大的答案!它确实是一个更接近我正在寻找的解决方案,但是,我要么未能正确实现它,要么它没有多大帮助,因为我仍然得到很多失败的解决方案,例如这个: 如您所见,X 的值是不可能的,因为您提到的红色单元格具有 1,2,3,4 的所有可能值。如果这是我的错误,请告诉我,并感谢您的帮助!1 1 3 4 2 3 1 1 2 2 4 4 2 1 1 4 4 3 3 1 3 3 2 X 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (x7)
0赞 MangoNrFive 8/24/2022
是的,你是对的,不幸的是,如果绿色单元格是否为空,我的 TLDR 中的第二个约束似乎需要始终遵循。但是,如果绿色单元格不是空的,则别无选择,因此可能会导致不可能的状态,如您所示。这很困难,因为问题已经浮出水面,x 右上角的 1 已经注定了。但是对于那个 1 也别无选择(或者如果上面还有另一行),所以这个谜题可能很早就变得不可能,然后只会在很久以后才会显现出来。
0赞 MangoNrFive 8/24/2022
但是,将问题分成两个独立问题的建议仍然有效。如果您可以修改您的软件以求解有效的光解和有效的暗解,这应该已经是一个显着的加速。然后,您可以将任何浅色解决方案与任何深色解决方案相结合,它应该是整个阵列的有效解决方案。约束条件基本上保持不变,但您只需将约束条件应用于一半的单元格即可。