[英]Calculate a list of cubes in Prolog
So I'm doing some Prolog in SWI-Prolog and I've come across a little snag. 所以我在SWI-Prolog中做一些Prolog,遇到了一些障碍。 I must create a list of cubes, given an input list.
给定输入列表,我必须创建一个多维数据集列表。 The code I currently have is
我目前拥有的代码是
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.
When I run that it gives an error, specifically... 当我运行它给出一个错误,特别是...
ERROR: '.'/2: Type error: `[]' expected, found `[8]' ("x" must hold one character)
Exception: (7) cbList([1, 2], _G296, []) ? creep
I'm not entirely sure why this error is occurring but it seems to happen around the very last line, Cubes is NewCubes. 我不完全确定为什么会发生此错误,但似乎发生在最后一行,即Cubes是NewCubes。 Any help is appreciated :)
任何帮助表示赞赏:)
I think you are trying to exercise a pattern known as accumulator , rewriting a binary relation with an added argument that holds intermediary results. 我认为您正在尝试使用一种称为“ 累加器”的模式,用包含中间结果的附加参数重写二进制关系。
Syntax errors apart, you should note that an accumulator it's useless here, because each element of a list is in relation only with the corresponding element of the other list. 除了语法错误之外,您还应该注意,这里的一个累加器是没有用的,因为一个列表的每个元素仅与另一个列表的相应元素相关。
library( apply ) has maplist /3 for such common case: 对于这种常见情况,library( apply )具有maplist / 3:
cube(N, C) :-
C is N^3.
cubes(Ns, Cs) :-
maplist(cube, Ns, Cs).
and library( clpfd ) has interesting features that allow (in integer domain) a better relational handling of arithmetic. 和library( clpfd )具有有趣的功能,这些功能允许(在整数域中)对算术进行更好的关系处理。 Replace cube above with
将上面的多维数据集替换为
:- [library(clpfd)].
cube(N, C) :-
N ^ 3 #= C.
and you are allowed to write 你被允许写
?- cubes(X,[1,8,27]).
X = [1, 2, 3].
First, you're making different cubes
predicates with differing numbers of arguments. 首先,您要使用不同数量的参数制作不同的
cubes
谓词。 This is bound to cause both conceptual and syntactical problems, so at that point, re-think what you're doing. 这势必会引起概念和句法上的问题,因此在那时,请重新考虑您在做什么。 In this case, try to expand the ways you can use pattern matching and recursion:
在这种情况下,请尝试扩展使用模式匹配和递归的方式:
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).
In this case, one can also accomplish the desired goal with a difference list : 在这种情况下,还可以通过差异列表来实现期望的目标:
cubes( [] , [] ) .
cubes( [X|Xs] , [Y|Ys] ) :-
Y is X*X*X ,
cubes( Xs , Ys )
.
The output list is built as we traverse the source list, recursing down. 当我们遍历源列表并向下递归时,将构建输出列表。 The final goal
cubes([],[])
unifies the empty list []
with the tail of the output list, making it a correct list. 最终目标
cubes([],[])
将空列表[]
与输出列表的末尾统一起来,使其成为正确的列表。
The other approach is to use an accumulator, which builds the output in reverse order, then reverses it: 另一种方法是使用累加器,该累加器以相反的顺序构建输出,然后将其反向:
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 )
.
Both are (our should be) properly tail recursive. 两者都是(我们应该是)正确的尾递归。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.