所以我在SWI-Prolog做一些Prolog,我遇到了一些障碍。在给定输入列表的情况下,我必须创建一个立方体列表。我目前的代码是
cubes([Head|Tail],Cubes) :-
cubes([Head|Tail],Cubes,[]).
cubes([Head|Tail],Cubes,ActualCubes) :-
X is Head^3,
append(ActualCubes,[X],NewCubes),
cubes(Tail,Cubes,NewCubes).
cubes([Tail],Cubes,ActualCubes) :-
X is Tail^3,
append(ActualCubes,[X],NewCubes),
Cubes is NewCubes.
当我运行它时会出错,具体而言......
ERROR: '.'/2: Type error: `[]' expected, found `[8]' ("x" must hold one character)
Exception: (7) cbList([1, 2], _G296, []) ? creep
我不完全确定为什么会出现这种错误,但它似乎发生在最后一行,Cubes是NewCubes。任何帮助表示赞赏:)
答案 0 :(得分:5)
我认为您正在尝试使用称为 accumulator 的模式,使用包含中间结果的添加的参数重写二元关系。
除了语法错误之外,你应该注意一个累加器在这里没用,因为列表中的每个元素只与关联与另一个列表的对应元素。
cube(N, C) :-
C is N^3.
cubes(Ns, Cs) :-
maplist(cube, Ns, Cs).
和库(clpfd)具有有趣的功能,允许(在整数域中)更好的关系处理算术。用
替换上面的多维数据集:- [library(clpfd)].
cube(N, C) :-
N ^ 3 #= C.
你可以写
?- cubes(X,[1,8,27]).
X = [1, 2, 3].
答案 1 :(得分:1)
首先,您使用不同数量的参数创建不同的cubes
谓词。这必然会导致概念和语法问题,所以在这一点上,重新思考你在做什么。在这种情况下,尝试扩展模式匹配和递归的方式:
cubes([],[]).
cubes([H|T], [Y|Z]):-
Y is H*H*H,
cubes(T,Z).
betterCubes([],[]).
betterCubes([H|T], [Y|Z]):-
(
var(Y) , nonvar(H) -> Y is H*H*H
; nonvar(Y) , var(H) -> H is Y**(1.0/3.0)
; nonvar(Y) , nonvar(H) -> H*H*H =:= Y
),
betterCubes(T,Z).
答案 2 :(得分:-1)
在这种情况下,还可以使用差异列表来实现所需目标:
cubes( [] , [] ) .
cubes( [X|Xs] , [Y|Ys] ) :-
Y is X*X*X ,
cubes( Xs , Ys )
.
输出列表是在遍历源列表时生成的,递归。最终目标cubes([],[])
将空列表[]
与输出列表的尾部统一起来,使其成为正确的列表。
另一种方法是使用累加器,它以相反的顺序构建输出,然后反转它:
cubes(Xs,Ys) :-
cubes(Xs,[],T) ,
reverse(T,Ys)
.
cubes( [] , Ys, Ys ).
cubes( [X|Xs] , Ts , Ys ) :-
T is X*X*X ,
cubes( Xs , [T|Ts] , Ys )
.
两者都是(我们应该)正确的尾递归。