2016-12-02 64 views
1

我怎样才能让我的Prolog程序输出序言乘以一个列表的元素

1*a*b*c

如果我输入simplify([1,a,b,c],S).? 目前结果将是

1 *(a *(b * c))。

simplify(S,S1):- 
    s(S,S1). 

s([H|T],C) :- T\=[],s(H,SA), s(T,SB), s0(SA*SB,C). 
s([H|T],H) :- T==[]. 
s(A,A). 

s0(A*B,S):- 
    S = A*B. 

感谢您的帮助。

回答

0

取决于序言你使用什么。 SWI内置foldl/4,就像其他语言的“减少”一样。所以,你可以简化你的程序如下:

s(B,A,A*B). 

simplify([H|L],E):- foldl(s,L,H,E). 
0

不知道那是你想要的,但使用atom_concat/3 ......

simplify([H],H). 

simplify([A | T], D) :- 
    simplify(T,B), 
    atom_concat(A, '*', C), 
    atom_concat(C, B, D). 

但你必须使用1为“原子”,让

simplify(['1',a,b,c], S), 
+0

不幸的是输出不需要是一个“复合” –

1

的区别在1*a*b*c1*(a*(b*c))之间是相关性,即括号的位置:

?- X = 1*a*b*c, X = ((One * A) * B) * C. 
X = 1*a*b*c, 
One = 1, 
A = a, 
B = b, 
C = c. 

这样做的一种方法是“从左侧折叠列表”,也就是说,计算列表的第一个元素的结果,与第二个元素结合,然后结合第三个元素等。这通常是使用累加器参数完成传递中间结果。相比之下,递归将“从右边开始”列表(将尾列表的结果与第一个元素相结合,而不是将最初的列表与最后一个元素组合在一起)。

这里是一个办法(看得很轻测试):

list_multexp([X|Xs], Multexp) :- 
    list_multexp(Xs, X, Multexp). % use first element as initial acc 

list_multexp([X], Acc, Acc * X). 
list_multexp([X|Xs], Acc, Multexp) :- 
    dif(Xs, []), 
    list_multexp(Xs, Acc * X, Multexp). 

这适用于你的例子:

?- list_multexp([1,a,b,c], Multexp). 
Multexp = 1*a*b*c ; 
false.