Robert Thomas
Robert Thomas

Reputation: 13

Prolog multiply elements of a list

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

Answers (3)

RdR
RdR

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

Isabelle Newbie
Isabelle Newbie

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

max66
max66

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

Related Questions