Prolog Count Occurrences in 2 lists - list

I want to compare 2 list, for each element.
Count the number of equal elements.
Im so close, please help me:
%list vs list%
count2([],[],0).
count2([H1|T1],[H2|T2],S):-
count(H1,[H2|T2],N),
count2(T1,[H2|T2],M),
S is N+M.
%1 element vs 1 list%
count(_, [], 0).
count(X, [X | T], N) :-
!, count(X, T, N1),
N is N1 + 1.
count(X, [_ | T], N) :-
count(X, T, N).
A test:
1 ?- count2([2],[1,2,3],S).
false.
Trace:
2 ?- count2([2],[1,2,3],S).
Redo: (5) read_history(h, '!h', [trace, end_of_file], '~! ?- ', _G154, _G155) ? creep
Correct to: "count2([2],[1,2,3],S)"?
Please answer 'y' or 'n'? yes
Call: (7) count2([2], [1, 2, 3], _G306) ? creep
Call: (8) count(2, [1, 2, 3], _G631) ? creep
Call: (9) count(2, [2, 3], _G631) ? creep
Call: (10) count(2, [3], _G631) ? creep
Call: (11) count(2, [], _G631) ? creep
Exit: (11) count(2, [], 0) ? creep
Exit: (10) count(2, [3], 0) ? creep
Call: (10) _G632 is 0+1 ? creep
Exit: (10) 1 is 0+1 ? creep
Exit: (9) count(2, [2, 3], 1) ? creep
Exit: (8) count(2, [1, 2, 3], 1) ? creep
Call: (8) count2([], [1, 2, 3], _G637) ? creep
Fail: (8) count2([], [1, 2, 3], _G637) ? creep
Redo: (11) count(2, [], _G631) ? creep
Fail: (11) count(2, [], _G631) ? creep
Fail: (10) count(2, [3], _G631) ? creep
Fail: (9) count(2, [2, 3], _G631) ? creep
Fail: (8) count(2, [1, 2, 3], _G631) ? creep
Fail: (7) count2([2], [1, 2, 3], _G306) ? creep
false.
(Returns the solution, but I have a problem with recursion)
Requested output #1:
?- count2([2],[1,2,3],S).
S = 1.
(2 is 1 time in the list).
Requested output #2:
?- count2([1,2],[1,2,3],S).
S = 2
(1 is 1 time in the list).
(2 is 1 time in the list).
Total = 2 equal elements.

A simpler solution would be to recurse on elements of the main list and check whether each element is a member of your test list:
count(_, [], 0).
count(Xs, [H|T], C) :-
( member(H, Xs)
-> C #= C1 + 1
; C1 = C
),
count(Xs, T, C1).

Answer:
count2([],[_|_],0).
count2([H1|T1],[H2|T2],S):-
count(H1,[H2|T2],N),
count2(T1,[H2|T2],M),
S is N+M.
count(_, [], 0).
count(X, [X | T], N) :-
!, count(X, T, N1),
N is N1 + 1.
count(X, [_ | T], N) :-
count(X, T, N).
Solved!

Related

Prolog basic exercise with lists gives stack size error

I'm starting to learn prolog, and I'm stuck with this problem, it would be really helpful if someone could tell me what I'm doing wrong and why is it wrong so I can learn.
Exercise
Write a predicate that follows the syntax:
supr_bigger(Elem,List,Result)
where Result is the list List, but with all of the elements bigger than Elem deleted.
Code
supr_bigger(_,[],[]).
supr_bigger(Elem,[X|Y],R) :- X =< Elem,
insert(X,R,R1),
supr_bigger(Elem,Y,R1).
supr_bigger(Elem,[X|Y],R) :- X > Elem, supr_bigger(Elem,Y,R).
insert(Z,L1,L2) :- choose(Z,L2,L1).
choose(X,[X|L],L).
choose(X,[Y|L1],[Y|L2]) :- choose(X,L1,L2).
When I try to test the code above, this error shows up:
?- supr_bigger(3,[3,2,5,4,1,2,6],R).
ERROR: Stack limit (1,0Gb) exceeded
ERROR: Stack sizes: local: 2Kb, global: 0,9Gb, trail: 0Kb
ERROR: Stack depth: 16, last-call:13%, Choice points: 11
A lot of thanks in advance.
You can use predicate trace/1 to find out what is wrong with your code:
?- trace, supr_bigger(3, [3,2,1,4], R).
Call: (11) supr_bigger(3, [3, 2, 1, 4], _4526) ? creep
Call: (12) 3=<3 ? creep
Exit: (12) 3=<3 ? creep
Call: (12) insert(3, _4526, _5168) ? creep
Call: (13) choose(3, _5210, _4526) ? creep
Exit: (13) choose(3, [3|_4526], _4526) ? creep
Exit: (12) insert(3, _4526, [3|_4526]) ? creep
Call: (12) supr_bigger(3, [2, 1, 4], [3|_4526]) ? creep
Call: (13) 2=<3 ? creep
Exit: (13) 2=<3 ? creep
Call: (13) insert(2, [3|_4526], _5482) ? creep
Call: (14) choose(2, _5524, [3|_4526]) ? creep
Exit: (14) choose(2, [2, 3|_4526], [3|_4526]) ? creep
Exit: (13) insert(2, [3|_4526], [2, 3|_4526]) ? creep
Call: (13) supr_bigger(3, [1, 4], [2, 3|_4526]) ? creep
Call: (14) 1=<3 ? creep
Exit: (14) 1=<3 ? creep
Call: (14) insert(1, [2, 3|_4526], _5796) ? creep
Call: (15) choose(1, _5838, [2, 3|_4526]) ? creep
Exit: (15) choose(1, [1, 2, 3|_4526], [2, 3|_4526]) ? creep
Exit: (14) insert(1, [2, 3|_4526], [1, 2, 3|_4526]) ? creep
Call: (14) supr_bigger(3, [4], [1, 2, 3|_4526]) ? creep
Call: (15) 4=<3 ? creep
Fail: (15) 4=<3 ? creep
Redo: (14) supr_bigger(3, [4], [1, 2, 3|_4526]) ? creep
Call: (15) 4>3 ? creep
Exit: (15) 4>3 ? creep
Call: (15) supr_bigger(3, [], [1, 2, 3|_4526]) ? creep
Fail: (15) supr_bigger(3, [], [1, 2, 3|_4526]) ?
As you can observe, when the input list is empty (call 15), the output list actually contains all the elements that should have been selected. However, the base clause in the recusive definition of supr_bigger/3 cannot be applied in this case, since lists [] (clause's third argument) and [1, 2, 3|_4526] (goal's third argument) do not match.
To solve the problem, you could modify your code to:
Close the open list [1, 2, 3|_4526], transforming it into [1, 2, 3].
Add a new argument to collect the final result.
But, since your code has many other problems, it's better to try a simpler approach:
supr_bigger(_, [], []).
supr_bigger(B, [X|Xs], [X|Ys]) :- X =< B, supr_bigger(B, Xs, Ys).
supr_bigger(B, [X|Xs], Ys) :- X > B, supr_bigger(B, Xs, Ys).
Example:
?- supr_bigger(3, [3,2,1,4], R).
R = [3, 2, 1] ;
false.
To eliminate spurious choice points, you can do as follows
supr_bigger(B, L, R) :-
best_supr_bigger(L, B, R).
best_supr_bigger([], _, []).
best_supr_bigger([X|Xs], B, R) :-
( X =< B
-> R = [X|Ys]
; R = Ys ),
best_supr_bigger(Xs, B, Ys).
Example:
?- supr_bigger(3, [3,2,1,4], R).
R = [3, 2, 1].

Prolog: Append complex terms in a list

I'm new with Prolog and I have a problem that I don't understand why.
I have a predicate (maybe wrong) that is to split a list in two lists. Something like that:
divide([],[],[]).
divide([PrimerEdificio|RestoEdificios], ListaA, ListaB) :-
divide(RestoEdificios, ListaParcialA, ListaParcialB),
append([PrimerEdificio], ListaParcialA, ListaA),
length(RestoEdificios, LongitudResto),
length(ListaA, LongitudA),
LongitudA > LongitudResto.
divide([PrimerEdificio|RestoEdificios], ListaA, ListaB) :-
length(RestoEdificios, LongitudResto),
length(ListaA, LongitudA),
LongitudA =< LongitudResto.
append(RestoEdificios, [], ListaB).
When I try to append the terms into the list (case 2) the variable is not being instantiated but if I do directly in console it works fine. Here debug:
[trace] 1 ?- divide([ed(3,5,6), ed(4,5,6), ed(5,6,7)], X, Y).
Call: (7) divide([ed(3, 5, 6), ed(4, 5, 6), ed(5, 6, 7)], _G3026, _G3027) ? creep
Call: (8) divide([ed(4, 5, 6), ed(5, 6, 7)], _G3140, _G3141) ? creep
Call: (9) divide([ed(5, 6, 7)], _G3140, _G3141) ? creep
Call: (10) divide([], _G3140, _G3141) ? creep
Exit: (10) divide([], [], []) ? creep
Call: (10) append([ed(5, 6, 7)], [], _G3144) ? creep
Exit: (10) append([ed(5, 6, 7)], [], _G3144) ? creep
I would hope that _G3144 (last sentence) is instantiated to [ed(5, 6, 7)].
Any help?

Prolog list permutation

I have the following code that generates all possible permutations of a list, but I can't figure it out why it is working.
remove(X,[X|T],T).
remove(X,[F|T],[F|T1]) :- remove(X,T,T1).
perm([X|Y],Z) :- perm(Y,W), remove(X,Z,W).
perm([],[]).
Could someone give me some explanation or send me to a reference, please?
I'm just picking up Prolog, so I don't know the correct terms, but I think the logic goes as following:
The rules for remove(X,L,T) is straightforward, it defines T as a list with X removed from L. For example, given T=[1], which L satisfies X=2? the answer is [1,2] or [2,1].
For perm, let's take the example of perm([1,2,3], P).
According to the definition, P is a permutation of [1,2,3] if W is a permuation of [2,3], where W is P with 1 removed.
Assuming we somehow know W is [2,3] or [3,2] through the magic of backtracking, then P must be [1,2,3],[2,1,3],[2,3,1],...
How did we find out permutation of [2,3] is [2,3] or [3,2]? It happens when W2 is a permutation of [3], where W2 is P2 with 2 removed.
Assuming we somehow know W2 is [3], then P2 must be [2,3] or [3,2].
How did we find out permutation of [3] is [3]? It happens when W3 is a permutation of [], where W3 is P3 with 3 removed. Since W3 must be [] due to the base case, then P3 must be [3].
Just learned about the trace mode, it provides a step-by-step explanation:
?- trace.
true.
[trace] 2 ?- perm([1,2],X).
Call: (7) perm([1, 2], _G22903) ? creep
Call: (8) perm([2], _G22988) ? creep
Call: (9) perm([], _G22988) ? creep
Exit: (9) perm([], []) ? creep
Call: (9) remove(2, _G22988, []) ? creep
Exit: (9) remove(2, [2], []) ? creep
Exit: (8) perm([2], [2]) ? creep
Call: (8) remove(1, _G22903, [2]) ? creep
Exit: (8) remove(1, [1, 2], [2]) ? creep
Exit: (7) perm([1, 2], [1, 2]) ? creep
X = [1, 2] ;
Redo: (8) remove(1, _G22903, [2]) ? creep
Call: (9) remove(1, _G22984, []) ? creep
Exit: (9) remove(1, [1], []) ? creep
Exit: (8) remove(1, [2, 1], [2]) ? creep
Exit: (7) perm([1, 2], [2, 1]) ? creep
X = [2, 1] ;
Redo: (9) remove(1, _G22984, []) ? creep
Fail: (9) remove(1, _G22984, []) ? creep
Fail: (8) remove(1, _G22903, [2]) ? creep
Redo: (9) remove(2, _G22988, []) ? creep
Fail: (9) remove(2, _G22988, []) ? creep
Fail: (8) perm([2], _G22988) ? creep
Fail: (7) perm([1, 2], _G22903) ? creep
false.

Why does using [H|T] as a parameter instead of a normal variable cause my predicate to fail?

I'm creating a predicate to remove a specified element from a list so remove(Xs,X,Ys) should hold if Ys is the result of removing all occurrences
of X from Xs. My initial failing predicate is shown below:
remove([],_,[]).
remove([H1|T1],H1,[H2|T2]) :- % e.g. [2,3] , 2, [3]
remove(T1,H1,[H2|T2]). % remove first head -> [3], 2, [3]
remove([H1|T1],Y,[H1|T2]) :- % heads match e.g. [1,2,3], 2, [1,3]
H1\==Y,
remove(T1,Y,T2). % remove heads -> [2,3], 2, [3]
This was failing but then I noticed that I had a redundant [H2|Y2] where I could have just used a variable e.g. Ys. I made this change thinking that it would still fail but instead it starting working. The working code is shown below:
remove([],_,[]).
remove([H1|T1],H1,Ys) :- % e.g. [2,3] , 2, [3]
remove(T1,H1,Ys). % remove first head -> [3], 2, [3]
remove([H1|T1],Y,[H1|T2]) :- % heads match e.g. [1,2,3], 2, [1,3]
H1\==Y,
remove(T1,Y,T2). % remove heads -> [2,3], 2, [3]
Can someone explain why changing [H2|T2] to Ys made it work?
Somewhere in the progression of the query, the pattern, remove([H|T], H, []) is coming up which will match the head of the second clause of your second version, remove([H1|T1], H1, Ys), but will not match the head of the second clause of your first version, remove([H1|T1], H1, [H2|T2]).
If you run trace on the query, remove([1, 2, 3, 2], 2, [1, 3]) using your first program version, you get:
Call: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep
Call: (7) 1\==2 ? creep
Exit: (7) 1\==2 ? creep
Call: (7) remove([2, 3, 2], 2, [3]) ? creep
Call: (8) remove([3, 2], 2, [3]) ? creep
Call: (9) 3\==2 ? creep
Exit: (9) 3\==2 ? creep
Call: (9) remove([2], 2, []) ? creep
Fail: (9) remove([2], 2, []) ? creep <---- NOTE THIS FAILURE! (no clause match)
Fail: (8) remove([3, 2], 2, [3]) ? creep
Redo: (7) remove([2, 3, 2], 2, [3]) ? creep
Fail: (7) remove([2, 3, 2], 2, [3]) ? creep
Fail: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep
The case remove([2], 2, []) will not match the second clause of your first implementation:
remove([H1|T1], H1, [H2|T2])...
So H1 = 2, T1 = [], but [H2|T2] is not unifiable with [].
But it will match the second clause of your second implementation:
remove([H1|T1], H1, Ys).
Here you get, H1 = 2, T1 = [], and Ys = []. Here it is in the trace for your second version:
[trace] ?- remove([1,2,3,2],2,[1,3]).
Call: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep
Call: (7) 1\==2 ? creep
Exit: (7) 1\==2 ? creep
Call: (7) remove([2, 3, 2], 2, [3]) ? creep
Call: (8) remove([3, 2], 2, [3]) ? creep
Call: (9) 3\==2 ? creep
Exit: (9) 3\==2 ? creep
Call: (9) remove([2], 2, []) ? creep <---- SUCCESS! (2nd clause match)
Call: (10) remove([], 2, []) ? creep <---- SUCCESS!
Exit: (10) remove([], 2, []) ? creep
Exit: (9) remove([2], 2, []) ? creep
Exit: (8) remove([3, 2], 2, [3]) ? creep
Exit: (7) remove([2, 3, 2], 2, [3]) ? creep
Exit: (6) remove([1, 2, 3, 2], 2, [1, 3]) ? creep

SWI-Prolog: Sum-List

I'm starting with Prolog, and i'm a bit confused...
I have a simple program:
sum(0, []).
sum(Total, [Head|Tail]) :- sum(Sum, Tail), Total is Head + Sum.
When i debug, i can see that Prolog first splits the list with Head and Tail, so the result is 0 + empty list, and AFTER THAT it starts to sum the numbers and adds it again to the list.
Can someone explain why it doesn't come to Total is Head + Sum.
first and then splits the list to Head and Tail again?
EDIT: Here is the trace:
[trace] ?- sum(X, [1,2,3]).
Call: (6) sum(_G345, [1, 2, 3]) ? creep
Call: (7) sum(_G424, [2, 3]) ? creep
Call: (8) sum(_G424, [3]) ? creep
Call: (9) sum(_G424, []) ? creep
Exit: (9) sum(0, []) ? creep
Call: (9) _G430 is 3+0 ? creep
Exit: (9) 3 is 3+0 ? creep
Exit: (8) sum(3, [3]) ? creep
Call: (8) _G433 is 2+3 ? creep
xit: (8) 5 is 2+3 ? creep
Exit: (7) sum(5, [2, 3]) ? creep
Call: (7) _G345 is 1+5 ? creep
Exit: (7) 6 is 1+5 ? creep
Exit: (6) sum(6, [1, 2, 3]) ? creep
X = 6.
Your definition puts addition on the stack. The optimization that avoids putting away the addition would be a special case of a general technique known as tail recursion.
The following definition can use tail recursion:
sum(X,L):-sum(0,L,X).
sum(X,[],X).
sum(N, [Head|Tail],Y) :- N1 is Head + N, sum(N1,Tail,Y).
It introduces an accumulator for the values of the partial sum and carries it with the tail of the list. Here is the trace of the execution of the sum(X,[1,2,3]) query.
?- trace, sum(S,[1,2,3]),notrace,nodebug.
Call: (7) sum(_G584, [1, 2, 3]) ? creep
Call: (8) sum(0, [1, 2, 3], _G584) ? creep
^ Call: (9) _G792 is 1+0 ? creep
^ Exit: (9) 1 is 1+0 ? creep
Call: (9) sum(1, [2, 3], _G584) ? creep
^ Call: (10) _G795 is 2+1 ? creep
^ Exit: (10) 3 is 2+1 ? creep
Call: (10) sum(3, [3], _G584) ? creep
^ Call: (11) _G798 is 3+3 ? creep
^ Exit: (11) 6 is 3+3 ? creep
Call: (11) sum(6, [], _G584) ? creep
Exit: (11) sum(6, [], 6) ? creep
Exit: (10) sum(3, [3], 6) ? creep
Exit: (9) sum(1, [2, 3], 6) ? creep
Exit: (8) sum(0, [1, 2, 3], 6) ? creep
Exit: (7) sum(6, [1, 2, 3]) ? creep
S = 6 .
Here is another version doing that. I have been using concept mapping software to help in designing code, I cannot do complicated stuff in my head.
sum(A, [], A).
sum(Total, [Head|Tail], AuxNum) :-
Sum is Head+AuxNum,
sum(Total, Tail, Sum).
1 ?- trace,sum(Total,[1,2,3],0).
Call: (7) sum(_G2090, [1, 2, 3], 0) ? creep
Call: (8) _G2221 is 1+0 ? creep
Exit: (8) 1 is 1+0 ? creep
Call: (8) sum(_G2090, [2, 3], 1) ? creep
Call: (9) _G2224 is 2+1 ? creep
Exit: (9) 3 is 2+1 ? creep
Call: (9) sum(_G2090, [3], 3) ? creep
Call: (10) _G2227 is 3+3 ? creep
Exit: (10) 6 is 3+3 ? creep
Call: (10) sum(_G2090, [], 6) ? creep
Exit: (10) sum(6, [], 6) ? creep
Exit: (9) sum(6, [3], 3) ? creep
Exit: (8) sum(6, [2, 3], 1) ? creep
Exit: (7) sum(6, [1, 2, 3], 0) ? creep
Total = 6.