我正在学习“七周内的七种语言”,我只是想从书中找到一个例子。它解决了一个迷你数独网格 (4x4)。

作者使用的是 gprolog,但我使用的是 swi-prolog(无论出于何种原因,我都无法让 gprolog 在我的 VM 上工作,但 swi-prolog 首先尝试工作)。

我在 VirtualBox 4.0.4 r70112 中运行 Ubuntu 10.04(希望这不太相关!)

这是我的 prolog 文件中的代码:

:- use_module(library(clpfd)).

valid([]).
valid([Head|Tail]) :-
    all_different(Head),    % in the book, this is 'fd_all_different'
    valid(Tail).

 % beginning of sudoku rule itself
sudoku(Puzzle, Solution) :-
Solution = Puzzle,
Puzzle = [S11, S12, S13, S14,
          S21, S22, S23, S24,
          S31, S32, S33, S34,
          S41, S42, S43, S44],
Puzzle ins 1..4,    % in the book, this is 'fd_domain'

Row1 = [S11, S12, S13, S14],
Row2 = [S21, S22, S23, S24],
Row3 = [S31, S32, S33, S34],
Row4 = [S41, S42, S43, S44],

Col1 = [S11, S21, S31, S41],
Col2 = [S12, S22, S32, S42],
Col3 = [S13, S23, S33, S43],
Col4 = [S14, S24, S34, S44],

Square1 = [S11, S12, S21, S22],
Square2 = [S13, S14, S23, S24],
Square3 = [S31, S32, S41, S42],
Square4 = [S33, S34, S43, S44],

valid([Row1, Row2, Row3, Row4,
       Col1, Col2, Col3, Col4,
       Square1, Square2, Square3, Square4]).

我(有意)更改的唯一部分是:
  • 在顶部添加 use_module(library(clpfd)).
  • fd_all_different(Head), 更改为 all_different(Head),
  • fd_domain(Puzzle, 1, 4), 更改为 Puzzle ins 1..4,

  • 这是来自 swipl 的调用
    ?- sudoku([_, _, 2, 3,
               _, _, _, _,
               _, _, _, _,
               3, 4, _, _],
    Solution).
    Solution = [4, 1, 2, 3, 2, 3, 4, 1, 1|...] ;
    false.
    

    该解决方案在它中断之前是正确的,此时 prolog 似乎确定没有解决方案。但是还有:
    4 1 2 3
    2 3 4 1
    1 2 3 4
    3 4 1 2
    

    我已经搜索了代码以查找拼写错误或错位的列,但一直无法找到其来源。有任何想法吗?

    最佳答案

    在我看来,您依赖 SWI-Prolog 中的默认显示来编写代表解决方案的列表,这是 SWI-Prolog 的一个特性,在这种情况下它不会打印长列表的所有条目,而是替换带有“省略号”的九个项目后的尾部......

    当您将 write(Puzzle) 添加到目标并因此看到整个列表时,您偶然发现了这一点。 SWI-Prolog 的网站 has a FAQ about this "abbreviation" of lists

    关于prolog - Prolog 中的迷你数独求解器在中途停止,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5617126/

    10-14 05:46