如何在Prolog中找到“生成和测试”任务的所有解决方案?

时间:2014-09-16 13:19:59

标签: prolog

我想用Prolog解决以下问题,以改进/测试我的Prolog知识。

  

找到三个数字X,Y和Z,使得base10中的XYZ等于base9中的ZYX

来源:Coffee Time Challenges

由于我已经用其他语言解决了它,我知道解决方案是:

  • (X,Y,Z)=(0,0,0)
  • (X,Y,Z)=(4,4,5)

我通过生成X,Y,Z(10 ^ 3 = 1000种组合)的所有组合并测试条件是否为真来解决其他语言的问题。

使用Prolog进行测试

使用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,我想我必须在这里使用它,但到目前为止我从未(成功)使用它。你能告诉我如何打印这个问题的所有解决方案吗?

1 个答案:

答案 0 :(得分:7)

Prolog变量以大写字母或下划线开头,因此base9base10都不是变量。如果将其更改为Base9Base10,则您的解决方案将适用于具体的实例化。

要使其适用于变量,并避免生成所有组合,请考虑使用约束,这通常会显着减少搜索空间,并且是较低级算术的更通用的替代方法。例如,在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