2013-12-09 4 views
3

프롤로그 초보자로서 저는 이진 스도쿠 해결사를 구현하려고했습니다 (코드는 swi-prolog입니다). 진 스도쿠 여기에 설명 : 다음과 같은 쿼리를 수행 할 때 https://cstheory.stackexchange.com/questions/16982/how-hard-is-binary-sudoku-puzzleswi 프롤로그에서 이진 스도쿠

그러나 : 이제

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

을 해결책이있는 한 분명히이 false를 반환하지 말아야 ... 왜 이런 일이/얼마나 내가 할 수있는 이것을 고쳐라? 논리적으로이 경우에는 소리를하지 않는 대신 (\+)/1

:-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). 
+0

label (Row)은 문제를 해결하는 것 같지만 왜 작동합니까? clpfd 설명서의 예제 스도쿠 솔버에서 레이블을 만들 수 없습니다 (아마도 all_distinct에 함축적입니까?) – camel

+1

더 큰 너비로 갈 때 나는 다른 구속 조건을 가지고있을뿐만 아니라 라틴 사각형이라고 부르지 않을 것입니다. 심지어 하나도 닮은하지 않습니다 ... 또한, "binary sudoku"라고 입력하면 Google에 설명하는 것과 동일한 퍼즐이 발견됩니다. – camel

답변

3

은 순수한 제약 dif/2를 사용 : 귀하의 코드가 당신의 기대 작품으로 선 not(member(X,Y))을 변경

maplist(dif(X), Y)

예 쿼리 (나는 또한 대신에 a_more_readable_naming_convention을 사용해야 함을주의하십시오.)

+1이 작업에 적합한 CLP (FD)를 사용합니다.

+0

Hehe, 프롤로그가 왜 이렇게했는지 설명했을뿐만 아니라 예상대로 작동하게하는 수정 사항을 제공했습니다. 나는 또한 유효하지 않은 (유효하지 않은) 변경되었습니다. 큰 퍼즐 (12X12)을 주면 글로벌 스택이 부족합니다. 이것은 내 간단한 알고리즘의 한계입니까, 아니면 보지 못하는 빠른 수정이 있습니까? – camel

+1

새 코드를 다른 질문으로 표시하십시오. 이제는 다른 질문이므로 새 질문을 올리십시오. – mat