prolog数独块算法?

时间:2011-06-04 15:02:32

标签: algorithm list prolog sudoku

如何在prolog中获取块的所有元素?大小可以在我的代码中改变动态,因此块大小不同,4x4 = 4个元素,9x9 = 9个元素等。块被切割成正方形,因此在4x4中水平长度是圆形(sqrt(4))= 2和垂直块的长度是圆形(sqrt(4))= 2.和9x9 ... sqrt(9)..所以块的高度和宽度是3.我需要一个算法来使元素有效。

我的sudokulists以这种方式建立:

  

L = [                   [4,3,1,2],           [2,1,4,3],           [3,4,2,1],           [1,2,3,4]                ],

这是一个列表,其中包含sudoku中的行列表。检查行和列是没有问题的, - > all_different检查行,转置整个List,all_different检查转置列表。

但是由于数独的动态大小,我无法编写块的修复代码。所以有人有任何想法?我考虑过flatten(L)并使用偏移来获得正确的块,但这样做似乎很难吗?

请帮助我!

2 个答案:

答案 0 :(得分:2)

一个可能的解决方案如下(假设你有blocksize x blocksize块大小blocksize x blocksize - 在标准数独中所有数字相等,可以调整匹配其他布局)

  1. a = [],...,[]成为blocksize存储桶的列表。
  2. 将每一行划分为blocksize部分。
  3. 将第一部分放入第一个桶中,将第二部分放入第二个桶中,依此类推。如果你再次使用第一个桶到达最后一个桶。
  4. 完全展开a
  5. 将结果再次分区为blocksize x blocksize
  6. 在你的例子中:

    L=[ [4,3,1,2], [2,1,4,3], [3,4,2,1], [1,2,3,4] ]
    Partitions => [[4,3] [1,2] [2,1] [4,3] [3,4] [2,1] [1,2] [3,4]]
    Bucketed => [[4,3] [2,1] [3,4] [1,2]] [[1,2] [4,3] [2,1] [3,4]]
    Flattened => [4,3,2,1,3,4,1,2,1,2,4,3,2,1,3,4]
    Partitioned => [4,3,2,1], [3,4,1,2], [1,2,4,3], [2,1,3,4]]
    

答案 1 :(得分:1)

这是一些简单的Prolog,用于在列表列表表示中转置矩阵。我们的想法是通过从每个现有行中拉出头来创建一个新的“第一行”,然后递归到“剩余”尾部列表中。

transpose([[ ]|_],[ ]) :- !.
transpose(A,[H|T]) :-
    decap_List(A,H,B),
    transpose(B,T).

decap_List([ ],[ ],[ ]).
decap_List([[H|T]|Rows],[H|Hs],[T|Ts]) :-
    decap_List(Rows,Hs,Ts).

例如:

?- transpose([[1,2,3],[4,5,6],[7,8,9]],X).

X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 

但是请注意,对于大小为K²xK²的广义数独矩阵,在每个“框”中也有“所有不同”的条目,其大小为 KxK 平铺矩阵。使用与以前相同的设计,您还需要一个谓词将数独矩阵重新打包到“盒子”列表列表中。

要做到这一点,只需要一个进一步的谓词,将矩阵“分割”成每组 K 行。

part_K_rows([ ],_,[ ]) :- !.
part_K_rows(A,K,[H|T]) :-
    get_K_rows(A,K,H,B),
    part_K_rows(B,K,T).

get_K_rows(A,0,[ ],A) :- !.
get_K_rows([H|T],K,[H|Z],B),
    J is K-1,
    get_K_rows(T,J,Z,B).

part_K_rows / 3 应用于原始数独矩阵,然后转置每个生成的行分区并将 part_K_rows / 3 应用于每个分区将生成所需的列表“盒子”列表。