Prolog解决数独
Prolog solve Sudoku
我是 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
这里是 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]]).
希望你能帮我找出错误。
据我所知,它现在已经适合您了。不过,我还是想借此机会展示一些可能对您有用的提示:
事实与指令
首先,为什么您在回答中 post 的代码不起作用?
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)).
与您可能相信的相反,这不会导入 库!为什么?因为,就目前而言,这只是 use_module/1
形式的 Prolog 事实,类似于事实:
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()).
并且点位于 ()
中,因此您只需键入库的实际 名称 而不是 whose :- use_module...etc.
指令。
因此,要使用 library(clpfd)
,我只需键入:
C-c l clpfd
过了一段时间,我也厌烦了,干脆在我的 ~/.swiplrc
配置文件中添加了 :- use_module(library(clpfd)).
,因为我写的几乎所有程序都执行整数运算,所以这是有道理的让我在我编写的所有 Prolog 程序中使用 CLP(FD) 约束。例如,在 GNU Prolog 和 B-Prolog 等系统中也是如此。
但是,我仍然保留了 .emacs
定义,因为有时我需要导入其他库,我发现输入整个 :- use_module...
指令太麻烦且容易出错。
我是 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
这里是 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]]).
希望你能帮我找出错误。
据我所知,它现在已经适合您了。不过,我还是想借此机会展示一些可能对您有用的提示:
事实与指令
首先,为什么您在回答中 post 的代码不起作用?
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)).
与您可能相信的相反,这不会导入 库!为什么?因为,就目前而言,这只是 use_module/1
形式的 Prolog 事实,类似于事实:
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()).
并且点位于 ()
中,因此您只需键入库的实际 名称 而不是 whose :- use_module...etc.
指令。
因此,要使用 library(clpfd)
,我只需键入:
C-c l clpfd
过了一段时间,我也厌烦了,干脆在我的 ~/.swiplrc
配置文件中添加了 :- use_module(library(clpfd)).
,因为我写的几乎所有程序都执行整数运算,所以这是有道理的让我在我编写的所有 Prolog 程序中使用 CLP(FD) 约束。例如,在 GNU Prolog 和 B-Prolog 等系统中也是如此。
但是,我仍然保留了 .emacs
定义,因为有时我需要导入其他库,我发现输入整个 :- use_module...
指令太麻烦且容易出错。