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

Mar*_*oma 1 prolog

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

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

来源:咖啡时间的挑战

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

  • (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.
Run Code Online (Sandbox Code Playgroud)

但似乎有些不对劲:

?- is_solution(0,0,0).
false.

?- is_solution(4,4,5).
false.
Run Code Online (Sandbox Code Playgroud)

生成所有解决方案

我以为我可以通过swipl -f main.prolog以下方式获得解决方案:

is_solution(X,Y,Z).
ERROR: >=/2: Arguments are not sufficiently instantiated
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题

无需用户交互即可打印所有内容

最后,我想有一个可执行脚本,可以打印所有解决方案而无需用户交互.我已经看过findall,我想我必须在这里使用它,但到目前为止我从未(成功)使用它.你能告诉我如何打印这个问题的所有解决方案吗?

mat*_*mat 7

Prolog变量以大写字母或下划线开头,因此既不是变量base9也不base10是变量.如果将此更改为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.
Run Code Online (Sandbox Code Playgroud)

示例查询:

?- is_solution(X, Y, Z), label([X,Y,Z]).
X = Y, Y = Z, Z = 0 ;
X = Y, Y = 4, Z = 5.
Run Code Online (Sandbox Code Playgroud)

或者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)].
Run Code Online (Sandbox Code Playgroud)

要打印所有解决方案,请自行打印:

?- 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
Run Code Online (Sandbox Code Playgroud)