Prolog解决数独

asc*_*ath 3 prolog sudoku constraint-programming clpfd

我在Prolog很新,并在swi-prolog.org上找到了解决数据的例子.但我无法运行它.我抬头看着same_length而且只有same_length/2没有same_length/1.也是all_distinct/2没有all_distinct/0.http://www.swi-prolog.org/pldoc/man?section=clpfd-sudoku

这是我的错误:

ERROR: d:/.../prolog/sudoku.pl:5:10: Syntax error: Operator expected
% d:/.../prolog/sudoku compiled 0.00 sec, 0 clauses
Warning: The predicates below are not defined. If these are defined
Warning: at runtime using assert/1, use :- dynamic Name/Arity.
Warning: 
Warning: all_distinct/1, which is referenced by
Warning:        d:/.../prolog/sudoku.pl:16:8: 2-nd clause of blocks/3
Run Code Online (Sandbox Code Playgroud)

这是SWI-Prolog示例的代码:

    use_module(library(clpfd)). 

    sudoku(Rows) :-
        length(Rows, 9), maplist(same_length(Rows), Rows),
        append(Rows, Vs),
        Vs in 1..9,
        maplist(all_distinct, Rows),
        transpose(Rows, Columns),
        maplist(all_distinct, Columns),
        Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
        blocks(As, Bs, Cs),
        blocks(Ds, Es, Fs),
        blocks(Gs, Hs, Is).

blocks([], [], []). 
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
        all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
        blocks(Ns1, Ns2, Ns3).

problem(1, [[_,_,_,_,_,_,_,_,_],
            [_,_,_,_,_,3,_,8,5],
            [_,_,1,_,2,_,_,_,_],
            [_,_,_,5,_,7,_,_,_],
            [_,_,4,_,_,_,1,_,_],
            [_,9,_,_,_,_,_,_,_],
            [5,_,_,_,_,_,_,7,3],
            [_,_,2,_,1,_,_,_,_],
            [_,_,_,_,4,_,_,_,9]]).
Run Code Online (Sandbox Code Playgroud)

我希望你能帮助我找到我的错误.

mat*_*mat 6

据我所知,它现在已经适合你了.但是,我仍然希望借此机会展示一些可能对您有用的提示:

事实与指令

首先,为什么你在答案中发布的代码不起作用?

Prolog消息已经给出了一个非常好的指示:

Warning: The predicates below are not defined. ...
...
all_distinct/1, which is referenced by

这表明你实际上在某个地方的代码中使用all_distinct/1(而不是 all_distinct/2!),并且它不可用.

为什么?因为all_distinct/1可用library(clpfd),并且您没有导入该库!

这是初学者中非常常见的错误.看一下程序中的以下行:

    use_module(library(clpfd)). 

与您可能认为的相反,这不会导入库!为什么?因为,就目前而言,这只是形式的Prolog事实use_module/1,类似于以下事实:

    name(bob).

其中,同样地,没有名字bob,只是指出,name(bob) 持有.

您想要的是使用指令导入库.

指令是表单的术语,:-(D)也可以写成,:- D因为(:-)/1它是前缀  运算符.

因此,你打算写的是:

:- use_module(library(clpfd)). 

这是表单的术语:-(T),并在加载文件时作为指令处理.

便利性定义

就个人而言,我经常编写小型Prolog程序,其中大多数都使用CLP(FD)约束.在某些时候,我厌倦了添加:- use_module(library(clpfd)).到我的所有程序,所以我将以下定义添加到我的  ~/.emacs:

(global-set-key "\C-cl" (lambda ()
                          (interactive)
                          (insert ":- use_module(library()).")
                          (forward-char -3)))

当您按下时C-c l,会在以下位置插入以下代码段:

:- use_module(library()).

并且point位于the,()因此您只需键入库的实际  名称而不是其:- use_module...etc.指令.

所以,要使用library(clpfd),我只需输入:

C-c l clpfd

过了一会儿,我也厌倦了,并且只是添加:- use_module(library(clpfd)).到我的~/.swiplrc配置文件中,因为我编写的几乎所有程序都执行整数运算,所以我在所有Prolog程序中都可以使用CLP(FD)约束我是有意义的写.例如,在GNU Prolog和B-Prolog等系统中也是如此.

但是,我仍然保留了.emacs定义,因为有时我需要导入其他库,并且我发现输入整个:- use_module...指令太麻烦且容易出错.