【发布时间】:2020-12-30 18:18:57
【问题描述】:
我想使用 Prolog 解决 Dan Finkel 的 "the giant cat army riddle"。
基本上,您从[0] 开始,然后使用以下三种操作之一构建此列表:添加5、添加7 或获取sqrt。当您设法建立一个列表,使2、10 和14 按顺序出现在列表中并且它们之间可以有其他数字时,您就成功完成了游戏。
规则还要求所有元素都是不同的,它们都是<=60,并且都是整数。
例如,从[0] 开始,您可以应用(add5, add7, add5),这将导致[0, 5, 12, 17],但由于它没有按顺序排列的2、10、14,因此无法满足游戏要求。
我认为我已经成功地编写了所需的事实,但我不知道如何实际构建列表。我认为使用dcg 是一个不错的选择,但我不知道如何。
这是我的代码:
:- use_module(library(lists)).
:- use_module(library(clpz)).
:- use_module(library(dcgs)).
% integer sqrt
isqrt(X, Y) :- Y #>= 0, X #= Y*Y.
% makes sure X occurs before Y and Y occurs before Z
before(X, Y, Z) --> ..., [X], ..., [Y], ..., [Z], ... .
... --> [].
... --> [_], ... .
% in reverse, since the operations are in reverse too.
order(Ls) :- phrase(before(14,10,2), Ls).
% rule for all the elements to be less than 60.
lt60_(X) :- X #=< 60.
lt60(Ls) :- maplist(lt60_, Ls).
% available operations
add5([L0|Rs], L) :- X #= L0+5, L = [X, L0|Rs].
add7([L0|Rs], L) :- X #= L0+7, L = [X, L0|Rs].
root([L0|Rs], L) :- isqrt(L0, X), L = [X, L0|Rs].
% base case, the game stops when Ls satisfies all the conditions.
step(Ls) --> { all_different(Ls), order(Ls), lt60(Ls) }.
% building the list
step(Ls) --> [add5(Ls, L)], step(L).
step(Ls) --> [add7(Ls, L)], step(L).
step(Ls) --> [root(Ls, L)], step(L).
代码发出以下错误,但我没有尝试跟踪它或任何东西,因为我确信我使用 DCG 不正确:
?- phrase(step(L), X).
caught: error(type_error(list,_65),sort/2)
我正在使用 Scryer-Prolog,但我认为所有模块都可以在 swipl 中使用,例如 clpfd 而不是 clpz。
【问题讨论】: