解决任何二次数独,所以数量为4,9,16,25的数独......而不需要对正常数独场的子单元进行硬编码。#34;块#34; < / p>
使用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]]
答案 0 :(得分:0)
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个空列表,因此我们必须在检查终止之前将其展平。