2009-11-20 86 views
7

我想了解一些关于swi-prolog(超出基本的,无用的程序)。序言:通过示例学习

任何人都可以解释(也许在伪代码)这个数独求解器和相关函数在做什么?如果您需要更多参考资料,请参阅swi-prolog的CLP(FD)软件包。

谢谢!

:- use_module(library(clpfd)). 
sudoku(Rows) :-             
     length(Rows, 9), maplist(length_(9), Rows),     
     append(Rows, Vs), Vs ins 1..9,        
     maplist(all_distinct, Rows),        
     transpose(Rows, Columns), maplist(all_distinct, Columns), 
     Rows = [A,B,C,D,E,F,G,H,I],         
     blocks(A, B, C), blocks(D, E, F), blocks(G, H, I).   


length_(L, Ls) :- length(Ls, L).         

blocks([], [], []).             
blocks([A,B,C|Bs1], [D,E,F|Bs2], [G,H,I|Bs3]) :-     
     all_distinct([A,B,C,D,E,F,G,H,I]),       
     blocks(Bs1, Bs2, Bs3).          


problem(1, [[_,_,_,_,_,_,_,_,_],         
      [_,_,_,_,_,3,_,8,5],         
      [_,_,1,_,2,_,_,_,_],         
      [_,_,_,5,_,7,_,_,_],         
      [_,_,4,_,_,_,1,_,_],         
      [_,9,_,_,_,_,_,_,_],         
      [5,_,_,_,_,_,_,7,3],         
      [_,_,2,_,1,_,_,_,_],         
      [_,_,_,_,4,_,_,_,9]]). 
+2

学习序言就像学习其他语言一样。对原始人有良好的感觉,并且可以通过练习来剖析和理解任何程序。基本无用的程序是你的朋友。 – echo 2009-11-20 05:40:58

回答

3

数独/ 1基本上描述了Sudoku解决方案必须满足的约束,其中董事会被表示为九个长度为九的列表的列表。问题/ 2将部分实例化的板分配给问题编号。要使用它,你应该做

? - 问题(1,董事会),数独(董事会)。

您应该阅读the documentation中使用的谓词。

10

序言是一种不同的思维方式:你必须逻辑思考。

首先A :- B, C, D表示如果B和C和D为真,则A为真(成功)

的代码,你贴检查一个数独题的正确性的片段中,有三个条件:

  • 元素是行的所有不同
  • 元素是列
  • 元素都是不同所有不同的3×3块

它是如何工作的?

数独(行)为真,如果:

  1. length(Rows, 9) - >有以行9个元件
  2. maplist(_length(9), Rows) - >列表中的每一个元件上maplist检查谓词(第一参数)(第二个参数)。这意味着每一行的长度必须是9.
  3. maplist(all_distinct, Rows) - >和以前一样,但我们检查每一行是否有不同的(不相等的成对)元素。
  4. transpose(Rows, Columns), maplist(all_distinct, Columns) - >我们转了行成列的检查,如果他们都不同也由垂直方式选择它们
  5. Rows = [A,B,C,D,E,F,G,H,I] - >分裂排列表,并把每一个不同的变量A,B,C, D ...所以A将是第一行,B第二个等等
  6. blocks(A, B, C), blocks(D, E, F), blocks(G, H, I) - >这个谓词对于三元组行必须为真。

让我们来谈谈blocks的一部分,这是很有趣的理解。我们希望检查每个3x3块包含不同的值。我们怎么做到这一点?

假设有3行,对于第4到第6个(第2个块)和第7-9个(第3个块)的元素,每个行的前三个元素(第一个3x3块)的条件必须为真。

所以我们可以递归思考:blocks([],[],[])是平凡的,我们有空列表。

当您调用blocks谓词时选择了案例blocks([A,B,C|Bs1],[D,E,F|Bs2],[G,H,I|Bs3]),其参数与AT至少3个元素一起列出。因此,我们可以检查A,B,C,D,E,F,G,H和I是否都是不同的,然后我们将blocks递归地用作参数剩余列表(没有前三个元素)。这是Prolog的内容!

所以blocks将首先被调用三行9个元素,它将检查每行的前3个是不同的,并且自己调用3个包含6个元素的列表,再次检查并自己调用3个3元素列表,再次检查并用三个空列表(总是成功的trival case)自行调用。

+0

那么“追加(行,Vs),Vs ins 1..9”呢?它的意义是什么? – 2010-05-19 18:08:30