swi prolog中的二进制数独

时间:2013-12-09 00:24:49

标签: prolog swi-prolog sudoku clpfd

作为一个序言新手,我想尝试实现二进制数独求解器。(代码如下,swi-prolog)。这里解释了二进制数独:https://cstheory.stackexchange.com/questions/16982/how-hard-is-binary-sudoku-puzzle

但是,执行以下查询时:

binarySudoku([[1,0],[0,1]]). I get "true."
binarySudoku([[1,_],[_,_]]). I get "false."

现在显然它不应该返回false,因为有一个解决方案......为什么会发生这种情况/我该如何解决?

:-use_module(library(clpfd)).

validRow(Row) :-
    Row ins 0..1,
    length(Row,L),
    sum(Row,#=,L/2).

matrixNth(Matr,X,Y,El) :-
    nth1(Y,Matr,CurRow),
    nth1(X,CurRow,El).

allDifferent([]).
allDifferent([X|Y]) :-
    not(member(X,Y)),
    allDifferent(Y).


invalid(Rows,X,Y) :-
    AboveY is Y-1,
    BelowY is Y+1,
    matrixNth(Rows,X,Y,1),
    matrixNth(Rows,X,AboveY,1),
    matrixNth(Rows,X,BelowY,1).
invalid(Rows,X,Y) :-
    LeftX is X-1,
    RightX is X+1,
    matrixNth(Rows,X,Y,1),
    matrixNth(Rows,LeftX,Y,1),
    matrixNth(Rows,RightX,Y,1).

binarySudoku(Rows) :-
    length(Rows,Height),
    transpose(Rows,Cols),
    length(Cols,Height),
    maplist(validRow,Rows),
    foreach(between(1,Height,X),foreach(between(1,Height,Y),not(invalid(Rows,X,Y)))),
    allDifferent(Rows).

1 个答案:

答案 0 :(得分:3)

在这种情况下,使用纯约束(\+)/1而不是dif/2,而不是not(member(X,Y)):您的代码可以按预期将行maplist(dif(X), Y)更改为:

?- binary_sudoku([[1,A],[B,C]]), label([A,B,C]). A = B, B = 0, C = 1 ; false.

示例查询(请注意我还使用了a_more_readable_naming_convention而不是使用了以下方法):

{{1}}

+1使用CLP(FD),这非常适合此任务。