Finding sum of list in prolog shows factors of sum, not final sum result - prolog

I am trying to find the sum of a list in Prolog. Below is the total/sum code. It's close to working, however it returns the factors of the sum instead of just the sum. New to Prolog so I am not sure why this is happening.
sum([], 0).
sum([X|Tail],Sum):-
sum(Tail,Temp),
Sum=Temp+X.
Why does this result in the factors of the total being shown instead of the actual total value? The values add up to the correct answer, just not sure why it is displayed like this.
Input/Output:
Total = 0+3000.0+1900.0+1312.5+3000+1900+5000 ?

You're using term unification (=/2) instead of arithmetic evaluation (is/2) in the totalList/2 predicate:
totalList([], 0).
totalList([X|Tail],Total):-
totalList(Tail,Temp),
Total=Temp+X.
Rewrite as:
total_list([], 0).
total_list([X| Tail], Total):-
total_list(Tail, Temp),
Total is Temp + X.
The rename from totalList to total_list follows Prolog coding guidelines for predicate names.
Although not a bug, the performance of your predicate also suffers from not being tail-recursive. I.e. the recursive call in the second clauses is not the last goal in its body. Therefore, it will consume space proportional to the number of elements in the list. You can fix this problem by using an accumulator:
total_list(List, Sum) :-
total_list(List, 0, Sum).
total_list([], Sum, Sum).
total_list([X| Tail], Sum0, Sum):-
Sum1 is Sum0 + X,
total_list(Tail, Sum1, Sum).
This improved definition will run in constant space in most Prolog systems.

Related

Find length of a list of lists

I wrote a predicate which should calculate the length of a list:
my_length([],0).
my_length([_|L],N) :- my_length(L,N1), N is N1 + 1.
Can anyone help in adjusting this so that it will take a list of lists and output the total number of elements in the list of lists?
You have most of what you need: add a rule that computes the length of a list of lists that passes the head on to my_length:
my_length_lol([], 0).
my_length_lol([H|L],N) :- my_length(H,Add), my_length_lol(L,N1), N is N1 + Add.
As you can see, my_length_lol ("lol" stands for "List of Lists") is a near exact copy of my_length. The only difference is that it does not ignore list head, and uses my_length rule to compute the length of a sublist.
Demo.
Both the solution posted #dasblinkenlight and the original code in the question can be made tail-recursive by using accumulators, which would allow running in constant space:
my_length(List, Length) :-
my_length(List, 0, Length).
my_length([], Length, Length).
my_length([_| Tail], Length0, Length) :-
Length1 is Length0 + 1,
my_length(Tail, Length1, Length).
my_length_lol(Lists, TotalLength) :-
my_length_lol(Lists, 0, TotalLength).
my_length_lol([List| Lists], TotalLength0, TotalLength) :-
my_length(List, Length),
TotalLength1 is TotalLength0 + Length,
my_length_lol(Lists, TotalLength1, TotalLength).
I am still not the biggest fan of foldl/4 and thus I find it much more natural to state:
xss_length(Xss, N) :-
maplist(length,Xss, Ns),
list_sum(Ns, N).
Still, this does not terminate for Xss = [_,_], xss_length(Xss, 2). But it's a start.
In this answer we use meta-predicate foldl/4 in combination with Prolog lambda expressions.
:- use_module(library(lambda)).
We define the predicate lists_length/2 like this:
lists_length(Xss,N) :-
foldl(\Xs^N0^N2^(length(Xs,N1),N2 is N0+N1), Xss, 0,N).
Sample query:
?- lists_length([[a,b,c],[],[d,e]], N).
N = 5.

Prolog Assigning integer to a variable

I'm new to Prolog, and using GNU Prolog, so no clp(fd) allowed. What I'm trying to do is for a given integer N, generate a list with elements of 1 ~ N. So set(3,T). will output T = [1,2,3].
Here is what I have so far:
set(0,[]).
set(N,T):-set(N-1,T1),append(T1,[N],T).
When I try set(2,T), it crashes. I debugged with trace, and find out that it's not evaluating N-1, but rather doing N-1-1-1...
Anyone can tell me how to solve this?
Thank you.
n_ups(N, Xs) :-
length(Xs, N),
numbered_from(Xs, 1).
numbered_from([], _).
numbered_from([I0|Is], I0) :-
I1 is I0+1,
numbered_from(Is, I1).
In fact, the complexity is hidden within length/2.
It should be:
set(N,T):- N2 is N-1, set(N2,T1), append(T1,[N],T).
Arithmetic operations are performed by using is/2. N-1 is a shorthand for -(N,1) (just like N2 is N-1 is shorthand for is(N2, N-1)), so you were just creating infinite tree -(-(-(-(...),1),1,1,1).
Little educational note:
If you want set/2 to be proper relation so it can answer queries like set(3,X), set(X, [1,2,3]) and set(X,Y) without error then you should write this predicate that way:
set(0, []).
set(Value, List) :-
length(List, Value),
append(ShorterList, [Value], List),
ValueMinusOne is Value - 1,
set(ValueMinusOne, ShorterList).
That way result of arithmetic operation is always possible to obtain because input value (lenght of the list) is either explicitly given or generated from length/1.

How do I find the least multiple of N in a list of numbers using Prolog?

I need to find the least multiple of N in a list of numbers.
leastMultiple/2
leastMultipleOfThree/2,
arg1= list of numbers,arg2= X (X is what we want to find, the least multiple of 3 in a list of numbers).
For example, find the least multiple of 3 in [7,9,15,22]. I have been staring at this for quite some time, and I'm not entirely sure where to begin. If you can simply help me wrap my head around the problem a bit, I'd be very thankful.
An earlier version of my answer was confused by the use of the word "least multiple." You want to find the multiples in the list, and retrieve the smallest. I understand now.
First we must detect a multiple of N. We can do this by dividing and looking at the remainder using the modulo operator, like this:
?- X is 7 mod 3.
X = 1.
?- X is 9 mod 3.
X = 0.
I will define a convenience method for this, is_multiple_of:
% multiple_of(X, N) is true if X is a multiple of N
multiple_of(X, N) :- 0 is X mod N.
Now we can simply say:
?- multiple_of(7, 3).
false.
?- multiple_of(9, 3).
true.
Now there are two ways to proceed. The efficient approach, which could easily be made tail recursive for greater performance, would be to walk the list once with an accumulator to hold the current minimum value. A less code-intensive approach would be to just filter the list down to all multiples and sort it. Let's look at both approaches:
% less code: using setof/3
leastMultipleOfThree(List, Result) :-
setof(X, (member(X, List), multiple_of(X, 3)), [Result|_]).
setof/3 evaluates its second term as many times as possible, each time retrieving the variable in its first term for inclusion in the result, the third term. In order to make the list unique, setof/3 sorts the result, so it happens that the smallest value will wind up in the first position. We're using member(X, List), multiple_of(X, 3) as a very simple generate-test pattern. So it's terse, but it doesn't read very well, and there are costs associated with building lists and sorting that mean it isn't optimal. But it is terse!
% more code: using an accumulator
leastMultipleOfThree(List, Result) :- leastMultipleOfThree(List, null, Result).
% helper
leastMultipleOfThree([], Result, Result) :- Result \= null.
leastMultipleOfThree([X|Xs], C, Result) :-
multiple_of(X, 3)
-> (C = null -> leastMultipleOfThree(Xs, X, Result)
; (Min is min(X, C),
leastMultipleOfThree(Xs, Min, Result)))
; leastMultipleOfThree(Xs, C, Result).
This is quite a bit more code, because there are several cases to be considered. The first rule is the base case where the list is extinguished; I chose null arbitrarily to represent the case where we haven't yet seen a multiple of three. The test on the right side ensures that we fail if the list is empty and we never found a multiple of three.
The second rule actually handles three cases. Normally I would break these out into separate predicates, but there would be a lot of repetition. It would look something like this:
leastMultipleOfThree([X|Xs], null, Result) :-
multiple_of(X, 3),
leastMultipleOfThree(Xs, X, Result).
leastMultipleOfThree([X|Xs], C, Result) :-
multiple_of(X, 3),
C \= null,
Min is min(X, C),
leastMultipleOfThree(Xs, Min, Result).
leastMultipleOfThree([X|Xs], C, Result) :-
\+ multiple_of(X, 3),
leastMultipleOfThree(Xs, C, Result).
This may or may not be more readable (I prefer it) but it certainly performs worse, because each of these rules creates a choice point that if/else conditional expressions within a rule do not. It would be tempting to use cuts to improve that, but you'll certainly wind up in a hellish labyrinth if you try it.
I hope it's fairly self-explanatory at this point. :)

Difference between 2 consecutive elements in Prolog

So my problem sounds like this: Given a list of integer numbers, generate the list of permutations with the property that the absolute value of the difference between 2 consecutive values from the permutation is <=3.
For example : L=[2,7,5] ==> [[2,5,7], [7,5,2]].
So far I wrote this
domains
list=integer*
lista=list*
predicates
perm(list,list)
permutations(list,lista,integer)
delete(integer,list,list)
diff(list,integer)
clauses
perm([],[]).
perm(Y,[A|X]):-
delete(A,Y,Y1),
perm(Y1,X).
delete(A,[A|X],X).
delete(A,[B|X],[B|Y]):-
delete(A,X,Y).
perm_aux(L,X,3):-
perm(L,X),
diff(X,R),
abs(R)<=3.
diff([],0).
diff(???):-
??????
permutations(L,R,3):-
findall(X,perm_aux(L,X,3),R).
So I'm stuck in the part where I make the difference. I have no idea how to do it for every 2 consecutive elements. Please help me.
I wouldn't have diff return a difference, but rather give it the max difference you want and have it either fail as soon as it hits a difference that is too big, or it succeeds.
So diff(List, Max). And calling it, instead of:
diff(X,R),
abs(R)<=3. % Note that this should be =<
You'd have:
diff(X, 3).
Then your base cases are:
diff([], _). % Empty list always succeeds
diff([_], _). % Single element list always succeeds
And your recursive case would look like:
diff([X,Y|T], Max) :-
abs(X-Y) =< Max,
diff([Y|T], Max).
If you would like diff to provide a maximum absolute difference of consecutive values, you could define it as:
max_diff(X, Max) :-
max_diff(X, 0, Max).
max_diff([], M, M).
max_diff([_], M, M).
max_diff([X,Y|T], MaxSoFar, Max) :-
Diff is abs(X-Y),
( Diff > MaxSoFar
-> max_diff([Y|T], Diff, Max)
; max_diff([Y|T], MaxSoFar, Max)
).

Prolog Summing Fields in a Database

I am learning Prolog and I understand how to calculate the sum of a list but I can't figure out how to compute the sum of the fields of a database.
Sample database:
tastiness(bacon,100,200,300,400,500).
tastiness(lettuce,3,5,6,7,12).
Sample output
(bacon,1500).
(lettuce,33).
Here's how to sum the values of a list in standard Prolog:
sumlist([], 0).
sumlist([X|Xs], Sum) :-
sumlist(Xs, SumTail),
Sum is X + SumTail.
If you have something like
bacon(100).
bacon(200).
bacon(300).
bacon(400).
bacon(500).
you could then use the findall predicate. The findall predicate works as follows: If you want Z = [100, 200, 300, 400, 500] (the list of all bacon numbers) you write findall(X, bacon(X), Z).
Here's how to sum all bacon numbers:
| ?- findall(X, bacon(X), AllBacon), sumlist(AllBacon, SumBacon).
AllBacon = [100,200,300,400,500]
SumBacon = 1500
yes
As a side note, the sum computation proposed by #aioobe is not optimal because on a very large list, you will run out of call stack memory.
A particular technique is to put the recursive call of the predicate as the last element of your predicate. This way, all preceding things being already computed, Prolog can flush the current context of the predicate while making the recursive call. On a list with 1M elements, that means than you will run with 1 context being kept instead of up to one million.
While it may not seem important to you for this particular exercise, the tail call optimization is what makes recursion as powerful as iteration, if you take space consumption into consideration. It's worth learning!
Here is a version on which Tail Call Optimization is performable:
sumlist(List, Result) :-
sumlist(List, 0, Result).
sumlist([], Acc, Acc).
sumlist([Item|List], Acc, Result) :-
NewAcc is Acc + Item.
sumlist(List, NewAcc, Result).
It makes use of an idiom you will encounter a lot in declarative programming: an accumulator (here named Acc). Its purpose is to hold the resulting value "up until now" during the recursion.

Resources