Reputation: 13
How can I get my Prolog program to output
1*a*b*c
If I input simplify([1,a,b,c],S).
?
At the moment the result would be
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.
Thanks for your help.
Upvotes: 1
Views: 835
Reputation: 116
Depends on what Prolog you're using. SWI has foldl/4 built in, which is like "reduce" in other languages. So, you could simplify your program to the following:
s(B,A,A*B).
simplify([H|L],E):- foldl(s,L,H,E).
Upvotes: 0
Reputation: 9378
The difference between 1*a*b*c
and 1*(a*(b*c))
is associativity, i.e., the position of the parentheses:
?- X = 1*a*b*c, X = ((One * A) * B) * C.
X = 1*a*b*c,
One = 1,
A = a,
B = b,
C = c.
One way to do this is to "fold over the list from the left", that is to say, compute a result for the first element of the list, combine with the second element, then the third, etc. This is typically done using an accumulator argument to pass the intermediate result. In contrast, your recursion folds the list "from the right" (combining a result for the tail list with the first element, instead of the initial list with the last element).
Here's a way (very lightly tested):
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).
This works for your example:
?- list_multexp([1,a,b,c], Multexp).
Multexp = 1*a*b*c ;
false.
Upvotes: 1
Reputation: 66200
Not sure that is what do you want but... using atom_concat/3
...
simplify([H],H).
simplify([A | T], D) :-
simplify(T,B),
atom_concat(A, '*', C),
atom_concat(C, B, D).
But you have to use 1
as an "atom", so
simplify(['1',a,b,c], S),
Upvotes: 0