我想用Prolog解决以下问题,以改进/测试我的Prolog知识。
找到三个数字X,Y和Z,使得base10中的XYZ等于base9中的ZYX
由于我已经用其他语言解决了它,我知道解决方案是:
我通过生成X,Y,Z(10 ^ 3 = 1000种组合)的所有组合并测试条件是否为真来解决其他语言的问题。
使用Prolog,我编写了以下测试程序:
is_solution(X, Y, Z) :- 9>=X, X>=0, 9>=Y, Y>=0, 9>=Z, Z>=0,
base10 is (100*X + 10*Y + Z), base9 is (9*9*Z+9*Y+X),
base10 = base9.
但似乎有些不对劲:
?- is_solution(0,0,0).
false.
?- is_solution(4,4,5).
false.
我以为我可以通过swipl -f main.prolog
简单地获得解决方案:
is_solution(X,Y,Z).
ERROR: >=/2: Arguments are not sufficiently instantiated
我该如何解决?
最后,我希望有一个可执行脚本,可以在没有用户交互的情况下打印所有解决方案。我看过findall
,我想我必须在这里使用它,但到目前为止我从未(成功)使用它。你能告诉我如何打印这个问题的所有解决方案吗?
答案 0 :(得分:7)
Prolog变量以大写字母或下划线开头,因此base9
和base10
都不是变量。如果将其更改为Base9
和Base10
,则您的解决方案将适用于具体的实例化。
要使其适用于变量,并避免生成所有组合,请考虑使用约束,这通常会显着减少搜索空间,并且是较低级算术的更通用的替代方法。例如,在SICStus和SWI-Prolog中:
:- use_module(library(clpfd)).
is_solution(X, Y, Z) :-
[X,Y,Z] ins 0..9,
9*9*Z+9*Y+X #= 100*X + 10*Y + Z.
示例查询:
?- is_solution(X, Y, Z), label([X,Y,Z]).
X = Y, Y = Z, Z = 0 ;
X = Y, Y = 4, Z = 5.
或findall/3
:
?- findall(triple(X,Y,Z), (is_solution(X, Y, Z), label([X,Y,Z])), Triples).
Triples = [triple(0, 0, 0), triple(4, 4, 5)].
要打印所有解决方案,请自行打印:
?- is_solution(X, Y, Z), label([X,Y,Z]), format("solution: ~w ~w ~w\n", [X,Y,Z]), false.
solution: 0 0 0
solution: 4 4 5