解决任何二次数独,所以大小为4,9,16,25的数独.不需要硬编码这些“块”,你的普通数独字段的子单元。
使用SWI-Prolog和clp(FD)库。
以如下格式给出的Sudokus (列表列表):
[[_,1,3,_],
[2,_,_,_],
[_,_,_,3],
[_,2,1,_]]程序调用时使用:
solve_sudoku([[_,1,3,_],[2,_,_,_],[_,_,_,3],[_,2,1,_]],L).
L = [[4, 1, 3, 2], [2, 3, 4, 1], [1, 4, 2, 3], [3, 2, 1, 4]]发布于 2017-12-09 19:27:33
来自this link的顶级。
sudoku(Rows) :-
length(Rows,N),
D is integer(sqrt(N)),
append(Rows,Vs),Vs ins 1..N,
maplist(all_distinct,Rows),
transpose(Rows,Columns),
maplist(all_distinct,Columns),
check_blocks(Rows,D),
maplist(label,Rows).在检查行和列没有重复之后,我们需要检查块,它们是D*D正方形。
过程check_blocks/2一次获取D行,并将它们传递给block_columns/4。
check_blocks(Rows,D) :-
length(BlockRows,D), append(BlockRows,Rest,Rows),
block_columns(BlockRows,D,[],[]),
check_blocks(Rest,D).
check_blocks([],_).现在我们有D行,假设每行包含一定数量(即D)的D列。但我们需要获得所有行的前D列,以便检查块。
因此,block_columns/4中的第一个子句遍历所有行,并将它们拆分为前缀(D列)和其余行。当Rows为空时,Bs是当前块,Rs是每行中其余的列。
block_columns([Row|Rows],D,Bs,Rs) :-
length(Cols,D), append(Cols,Rest,Row),
block_columns(Rows,D,[Cols|Bs],[Rest|Rs]).
block_columns([],D,Bs,Rs) :-
flatten(Bs,Ns), all_distinct(Ns),
flatten(Rs,Xs),
( Xs = [] ->
true
; block_columns(Rs,D,[],[]) ).第二个子句检查块,然后重新开始。当我们到达列的末尾时,Rs不会为空,而是包含D个空列表,因此我们必须在检查终止之前将其展平。
https://stackoverflow.com/questions/47728056
复制相似问题