Prolog multiply all elements of a list - prolog

I want to define a predicate in Prolog, prod_list/2 that multiplies every element of a list. I'm having problem with the empty list wish the product should be zero, instead i get false.
My code is
prod_list([H], H).
prod_list([H|T], Product) :- prod_list(T, Rest),
Product is H * Rest.
The results I get are
prod_list([4,3],Product). -> Product = 12
but when I do prod_list([], Product). I get false instead of Product = 0.
Please help.

Your problem is that no clause matches the empty list. In fact you have a recursive clause:
prod_list([H|T], Product) :- prod_list(T, Rest),
Product is H * Rest.
but its recursion terminates when there is only an element in the list:
prod_list([H], H).
So, in no case the empty list [] is matched by a clause, and for this reason, the answer is false (no match available).
To solve your problem you need to include an explicit clause for the empty list:
prod_list([],0).
prod_list([H],H).
prod_list([H|T], Product) :- prod_list(T, Rest), Product is H * Rest.
A different solution could be found considering that the product of an empty list should be (correctly) defined in this way:
product_of_list([], 1).
product_of_list([H|T], Product) :- product_of_list(T, Rest), Product is H * Rest
then you could add your “special” definition of prod_list:
prod_list([],0).
prod_list(List, Product) :- product_of_list(List, Product).
Edit
The last solution does not work for some interactive versions of Prolog (for instance Swish on-line), while it does work for SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.11). A solutions that should work for every version is the following:
prod_list([],0).
prod_list([H|T], Product) :- product_of_list([H|T], Product).
Thanks to user474491 for discovering this.

Renzo's answer is perfect. I just thought of functional treatment of lists when I saw your question. You can have them just in case you need them. If you define a function multiplication:
mul(V1,V2,R) :- R is V1*V2;
then you can use foldl in any of its variants:
?- foldl(mul, [1,2,10], 1, R).
R = 20 .
fold is a traditional functional calculation function that applies a function accumulating the temporal result.

Related

Prolog - Using Bagof

I've been stuck on a past paper question while studying for my exams.
The question is:
https://gyazo.com/ee2fcd88d67068e8cf7d478a98f486a0
I figured I've got to use findall/bagof/setof because I need to collect a set of solutions. Furthermore, setof seems appropriate because the list needs to be presented in descending order.
My solution so far is:
teams(List) :-
setof((Team, A),
(Team^team(Team, _, Wins, Draws, _), A is Wins*3 + Draws*1),
List).
However the problem is I don't quite get the answers all in one list. I'm very likely using Team^ incorrectly. I'd really appreciate pointers on how I can get a list of ordered tuples in terms of points. The output it gives me is:
X = [(queenspark,43)] ? ;
X = [(stirling,26)] ? ;
X = [(clyde,25)] ? ;
X = [(peterhead,35)] ? ;
X = [(rangers,63)] ? ;
Also, it's not really apparent what kind of order, if any it's in, so I'm also lost as to how setof is ordering.
Whats the best way to approach this question using setof?
Thanks.
Firstly, I would suggest to change (Team,A) to a pair representation A-Team with the A being in front since this is the total score of the team and thus the key you want to use for sorting. Then you would like to prefix the variables that should not be in the list with a ^ in front of the query you want to aggregate. See the following example:
?- setof(A-Team, P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1), List).
List = [25-clyde,26-stirling,35-peterhead,43-queenspark,63-rangers]
Since you asked, consider the following query with the pair ordering flipped to Team-A for comparison reasons:
?- setof(Team-A,P^Wins^Draws^L^(team(Team,P,Wins,Draws,L), A is Wins*3 + Draws*1),List).
List = [clyde-25,peterhead-35,queenspark-43,rangers-63,stirling-26]
Now the resulting list is sorted with respect to the teamnames. So A-Team is the opportune choice. You could then use the predicate lists:reverse/2 to reverse the order to a descending list and then define an auxilary predicate pair_second/2 that you can use with apply:maplist/3 to get rid of the leading scores in the pairs:
:- use_module(library(lists)).
:- use_module(library(apply)).
% team(+Name, +Played, +Won, +Drawn, +Lost)
team(clyde,26,7,4,15).
team(peterhead,26,9,8,9).
team(queenspark,24,12,7,5).
team(rangers,26,19,6,1).
team(stirling,25,7,5,13).
pair_second(A-B,B). % 2nd argument is 2nd element of pair
teams(Results) :-
setof(A-Team,
P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1),
List),
reverse(List,RList),
maplist(pair_second,RList,Results). % apply pair_second/2 to RList
If you query the predicate now you get the desired results:
?- teams(T).
T = [rangers,queenspark,peterhead,stirling,clyde]
Concerning your question in the comments: Yes, of course that is possible. You can write a predicate that describes a relation between a list of pairs and a list than only consists of the second element of the pairs. Let's call it pairlist_namelist/2:
pairlist_namelist([],[]).
pairlist_namelist([S-N|SNs],[N|Ns]) :-
pairlist_namelist(SNs,Ns).
Then you can define teams/1 like so:
teams(Results) :-
setof(A-Team,
P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1),
List),
reverse(List,RList),
pairlist_namelist(RList,Results).
In this case, besides maplist/3, you don't need pair_second/2 either. Also you don't need to include :- use_module(library(apply)). The example query above yields the same result with this version.

Prolog, finding largest value from a setOf list

I have a predicate which purpose is to print out which country that has the biggest area(one with biggest border = biggest area). This is how my predicate looks like:
/* If I write get_country(X, 'Europe'). then all the countries in Europe
that isn't bordering a sea gets printed out.
However as you can see I am creating a list
with all of the countries and then I want to
take the largest country from all of these
and print that one out. But instead
all of the countries gets printed out
with their length, ex: X = hungary ; 359 (length) ... */
get_country(Country, Region):-
encompasses(Country,Region,_),
not(geo_sea(_,Country,_)),
setof(Length, country_circumference(Country,Length), Cs),
largest(Cs, X),
write(X).
The predicates used within that predicate follows:
country_circumference(Country, X):-
setof(Length, get_border_length(Country, Length), Cs),
sum(Cs, X).
largest([X],X).
largest([X|Xs],R) :-
largest(Xs,Y),
R is max(X,Y).
Can anyone tell me what I am doing wrong here? How do I simply get all of my countries into the list and then traverse through the list to find the one with the biggest border instead of just printing them out one after one as I put them into the list? Thanks in advance.
Prolog defines a natural order of terms. For example, the following are true:
foo(3, z) #< foo(10, x)
bar(2, 9) #< foo(3, 1)
Note the use of the term comparison operator #< versus the numeric comparison <. The predicate, setof/3, will do term comparison.
If you want to find the country that has the longest border, then you can do so by taking advantage of the term comparison and collect like terms in setof/3 that have the item you want to sort by as the first argument. In this case, we'd want the circumference first. In addition, if I'm understanding the intended meaning of your get_country predicate correctly, you need to include the queries that define the countries you want to consider as part of the query in the setof/3:
get_country(Country, Region):-
setof(L-C-R, X^Y^Z^( encompasses(C, R, X),
\+ geo_sea(Y, C, Z),
country_circumference(C, L) ), Cs),
reverse(Cs, HighToLowAreas),
member(_-Country-Region, HighToLowAreas), !.
The member/2 at the end of the predicate clause will find the first element in the list HighToLowAreas that matches _-Country-Region, which will be the first element if Country and Region are initially uninstantiated.
The existential quantifiers X^Y^Z^ are needed to exclude these from being selectors in the query. Using _ won't do that in the context of setof/3. Here, we're using the term form, -(-(X,Y),Z) since it's conveniently written, X-Y-Z. But you could just as well use, foo(X, Y, Z) here. The reverse/2 puts the list Cs in descending order, and we just pick off the Country and Region from the head of that list with, [_-Country-Region].

Check if all numbers in a list are different in prolog

I want to create a rule in prolog that checks if there's a repeated number in a list.
For example:
for [1,2,3,4] it will return true.
for [1,2,3,3] it will return false because the 3 is repeated
I came up with this rule but it doesn't work
Different([]).
Different([H|T]):-
Member(H,T),
Different(T).
Any ideas?
a compact definition could be
all_diff(L) :- \+ (select(X,L,R), memberchk(X,R)).
i.e. all elements are different if we can't peek one and find it in the rest...
edit
Let's (marginally) improve efficiency: it's useless to check if X is member of the prefix sublist, so:
all_diff(L) :- \+ (append(_,[X|R],L), memberchk(X,R)).
The simplest way to check that all list members are unique is to sort list and check that length of the sorted list is equal of length of the original list.
different(X) :-
sort(X, Sorted),
length(X, OriginalLength),
length(Sorted, SortedLength),
OriginalLength == SortedLength.
Your solution doesn't work because of wrong syntax (facts and predicates should not begin with a capital letter) and a logic error. List is unique if head H is not a member of a tail T of a list and tail T is unique:
different([]).
different([H|T]):-
\+member(H,T),
different(T).
If all numbers in that list are integers, and if your Prolog implementation offers clpfd, there's no need to write new predicates of your own---simply use the predefined predicate all_different/1!
:- use_module(library(clpfd)).
Sample use:
?- all_different([1,2,3,4]).
true.
?- all_different([1,2,3,3]).
false.
Very Simple Answer...
The code:
unique([]).
unique([_,[]]).
unique([H|T]):-not(member(H,T)),unique(T).
Tests:
?-unique([1,2,3,4]).
true.
?-unique([1,2,3,3]).
false.
?-unique([a,b,12,d]).
true
?-unique([a,b,a]).
false
A neat way I came up with is the following:
If all members of a list are different from each other, then if I tell prolog to choose all pairs (I,J) such that I,J are members of the list and also I is equal to J, then for each element in the list it will only be able to find one such pair, which is the element with itself.
Therefore, if we can put all such pairs in a list, then the length of this list should be of the same length of the original list.
Here's my prolog code:
all_diff(L) :-
findall((I,J), (member(I, L), member(J, L), I == J), List),
length(L, SupposedLength),
length(List, CheckThis),
SupposedLength == CheckThis.
The rule provided in the question is very close to a correct answer with minimal library usage. Here's a working version that required only one change, the addition of \+ in the third row:
uniqueList([]).
uniqueList([H|T]):-
\+(member(H,T)),
uniqueList(T).
Explanation of the code for Prolog beginners: The member(H,L) predicate checks if element H is a member of the list L. \+ is Prolog's negation function, so the above code amounts to:
uniqueList([H|T]) returns true if: (H doesn't have a copy in T) and uniqueList(T)
Whereas the code by the original asker didn't work because it amounted to:
uniqueList([H|T]) returns true if: (H has a copy in T) and uniqueList(T)
*I renamed Different() to uniqueList() because it reads better. Convention is to reserve capital letters for variables.
This isn't very efficient, but for each number you can check if it appears again later. Like so:
Different([H|T]):-
CheckSingle(H, [T]),
Different([T]).
Checksingle(_,[]).
Checksingle(Elem, [H, T]):-
Elem != H,
Checksingle(Elem, [T]).

ERROR: "Out of global stack" when processing Prolog list of pairs

In SWI-Prolog, I have a list whose elements are pairs of the form Key-ValuesList. For instance, one such list may look like:
[1-[a,b],2-[],3-[c]]
I would like to transform this list into a nested list of pairs of the form Key-[Value], where Value is an element in ValuesList. The above example would be transformed into:
[[1-[a],2-[],3-[c]], [1-[b],2-[],3-[c]]]
My current solution is the following:
% all_pairs_lists(+InputList, -OutputLists).
all_pairs_lists([], [[]]).
all_pairs_lists([Key-[]|Values], CP) :-
!,
findall([Key-[]|R], (all_pairs_lists(Values,RCP), member(R,RCP)), CP).
all_pairs_lists([Key-Value|Values], CP) :-
findall([Key-[V]|R], (all_pairs_lists(Values,RCP), member(V,Value), member(R,RCP)), CP).
Using this predicate, a call of the form
all_pairs_lists([1-[a,b],2-[],3-[c]],OutputLists).
Binds the variable OutputLists to the desired result mentioned above. While it appears correct, this implementation causes an "Out of global stack" error when InputList has very long lists as values.
Is there a less stack consuming approach to doing this? It would seem like quite a common operation for this type of data structure.
Well, to sum it up, you're doing it wrong.
In Prolog, when we want to express a relation instead of a function (several results possible instead of one), we don't use findall/3 and member/2 directly. We rather state what the relation is and then maybe once it's done if we need a list of results we use findall/3.
Here what it means is that we want to express the following relation:
Take a list of Key-Values and return a list of Key-[Value] where Value is a member of the Values list.
We could do so as follows:
% The base case: handle the empty list
a_pair_list([], []).
% The case where the Values list is empty, then the resulting [Value] is []
a_pair_list([Key-[]|List], [Key-[]|Result]) :-
a_pair_list(List, Result).
% The case where the Values list is not empty, then Value is a member of Values.
a_pair_list([Key-[Not|Empty]|List], [Key-[Value]|Result]) :-
member(Value, [Not|Empty]),
a_pair_list(List, Result).
Once this relation is expressed, we can already obtain all the info we wish:
?- a_pair_list([1-[a, b], 2-[], 3-[c]], Result).
Result = [1-[a], 2-[], 3-[c]] ;
Result = [1-[b], 2-[], 3-[c]] ;
false.
The desired list is now just a fairly straight-forward findall/3 call away:
all_pairs_lists(Input, Output) :-
findall(Result, a_pair_list(Input, Result), Output).
The important thing to remember is that it's way better to stay away from extra logical stuff: !/0, findall/3, etc... because it's often leading to less general programs and/or less correct ones. Here since we can express the relation stated above in a pure and clean way, we should. This way we can limit the annoying use of findall/3 at the strict minimum.
As #Mog already explained clearly what the problem could be, here a version (ab)using of the basic 'functional' builtin for list handling:
all_pairs_lists(I, O) :-
findall(U, maplist(pairs_lists, I, U), O).
pairs_lists(K-[], K-[]) :- !.
pairs_lists(K-L, K-[R]) :- member(R, L).
test:
?- all_pairs_lists([1-[a,b],2-[],3-[c]],OutputLists).
OutputLists = [[1-[a], 2-[], 3-[c]], [1-[b], 2-[], 3-[c]]].

Passing results in prolog

I'm trying to make a function that has a list of lists, it multiplies the sum of the inner list with the outer list.
So far i can sum a list, i've made a function sumlist([1..n],X) that will return X = (result). But i cannot get another function to usefully work with that function, i've tried both is and = to no avail.
Is this what you mean?
prodsumlist([], 1).
prodsumlist([Head | Tail], Result) :-
sumlist(Head, Sum_Of_Head),
prodsumlist(Tail, ProdSum_Of_Tail),
Result is Sum_Of_Head * ProdSum_Of_Tail.
where sumlist/2 is a SWI-Prolog built-in.
Usage example:
?- prodsumlist([[1, 2], [3], [-4]], Result).
Result = -36.
The part "it multiplies the sum of the inner list with the outer list" isn't really clear, but I believe you mean that, given a list [L1,...,Ln] of lists of numbers, you want to calculate S1*..*Sn where Si is the sum of the elements in Li (for each i).
I assume the existence of plus and mult with their obvious meaning (e.g. plus(N,M,R) holds precisely when R is equal to N+M). First we need predicate sum such that sum(L,S) holds if, and only if, S is the sum of the elements of L. If L is empty, S obviously must be 0:
sum([],0).
If L is not empty but of the form [N|L2], then we have that S must be N plus the sum S2 of the elements in L2. In other words, we must have both sum(L2,S2) (to get S2 to be the sum of the elements of L2) and plus(N,S2,S). That is:
sum([N|L2],S) :- sum(L2,S2), plus(N,S2,S).
In the same way you can figure out the predicate p you are looking for. We want that p(L,R) holds if, and only if, R is the product of S1 through Sn where L=[L1,...,Ln] and sum(Li,Si) for all i. If L is empty, R must be 1:
p([],1).
If L is not empty but of the form [LL|L2], then we have that R must be the product of 'S', the sum of the elements of LL, and 'P', the product of the sums of the lists in L2. For S we have already have sum(LL,S), so this gives us the following.
p([LL|L2],R) :- sum(LL,S), p(L2,P), mult(S,P,R).
One thing I would like to add is that it is probably not such a good idea to see these predicates as functions you might be used to from imperative or functional programming. It is not the case that sumlist([1,..,n],X) returns X = (result); (result) is a value for X such that sumlist([1,...,n],X) is true. This requires a somewhat different mindset. Instead of thinking "How can I calculate X such that p(X) holds?" you must think "When does P(X) hold?" and use the answer ("Well, if q(X) or r(X)!") to make the clauses (p(X) :- q(X) and p(X) :- r(X)).
Here is a rewrite of Kaarel's answer (that's the intention anyway!) but tail-recursive.
prodsumlist(List, Result) :-
xprodsumlist(List,1,Result).
xprodsumlist([],R,R).
xprodsumlist([Head|Rest],Sofar,Result) :-
sumlist(Head, Sum_Of_Head),
NewSofar is Sofar * Sum_Of_Head,
xprodsumlist(Rest, NewSofar, Result).

Resources