I'm learning Prolog right now and have trouble understanding how Prolog uses these predicates to access the n-th element in the given list.
elementAt([Element|_], 0, Element).
elementAt([_|Tail], N, Element) :-
elementAt(Tail, N1, Element),
N is N1 + 1.
I use swi-prologs trace command to understand how the following expression is solved.
elementAt([0,1,2,3,4,5,6,7], 5, E).
I understand parts of the trace but not everything, so I copied the trace with line numbers for easier reference. My question is below the trace output.
1 Call: (8) elementAt([0, 1, 2, 3, 4, 5, 6, 7], 5, _6554) ? creep
2 Call: (9) elementAt([1, 2, 3, 4, 5, 6, 7], _6836, _6554) ? creep
3 Exit: (9) elementAt([1, 2, 3, 4, 5, 6, 7], 0, 1) ? creep
4 Call: (9) 5 is 0+1 ? creep
5 Fail: (9) 5 is 0+1 ? creep
6 Redo: (9) elementAt([1, 2, 3, 4, 5, 6, 7], _6836, _6554) ? creep
7 Call: (10) elementAt([2, 3, 4, 5, 6, 7], _6836, _6554) ? creep
8 Exit: (10) elementAt([2, 3, 4, 5, 6, 7], 0, 2) ? creep
9 Call: (10) _6840 is 0+1 ? creep
10 Exit: (10) 1 is 0+1 ? creep
11 Exit: (9) elementAt([1, 2, 3, 4, 5, 6, 7], 1, 2) ? creep
12 Call: (9) 5 is 1+1 ? creep
13 Fail: (9) 5 is 1+1 ? creep
14 Redo: (10) elementAt([2, 3, 4, 5, 6, 7], _6836, _6554) ? creep
15 Call: (11) elementAt([3, 4, 5, 6, 7], _6836, _6554) ? creep
16 Exit: (11) elementAt([3, 4, 5, 6, 7], 0, 3) ? creep
17 Call: (11) _6840 is 0+1 ? creep
18 Exit: (11) 1 is 0+1 ? creep
19 Exit: (10) elementAt([2, 3, 4, 5, 6, 7], 1, 3) ? creep
20 Call: (10) _6846 is 1+1 ? creep
21 Exit: (10) 2 is 1+1 ? creep
22 Exit: (9) elementAt([1, 2, 3, 4, 5, 6, 7], 2, 3) ? creep
23 Call: (9) 5 is 2+1 ? creep
24 Fail: (9) 5 is 2+1 ? creep
25 Redo: (11) elementAt([3, 4, 5, 6, 7], _6836, _6554) ? creep
26 Call: (12) elementAt([4, 5, 6, 7], _6836, _6554) ? creep
27 Exit: (12) elementAt([4, 5, 6, 7], 0, 4) ? creep
28 Call: (12) _6840 is 0+1 ? creep
29 Exit: (12) 1 is 0+1 ? creep
30 Exit: (11) elementAt([3, 4, 5, 6, 7], 1, 4) ? creep
31 Call: (11) _6846 is 1+1 ? creep
32 Exit: (11) 2 is 1+1 ? creep
33 Exit: (10) elementAt([2, 3, 4, 5, 6, 7], 2, 4) ? creep
34 Call: (10) _6852 is 2+1 ? creep
35 Exit: (10) 3 is 2+1 ? creep
36 Exit: (9) elementAt([1, 2, 3, 4, 5, 6, 7], 3, 4) ? creep
37 Call: (9) 5 is 3+1 ? creep
38 Fail: (9) 5 is 3+1 ? creep
39 Redo: (12) elementAt([4, 5, 6, 7], _6836, _6554) ? creep
40 Call: (13) elementAt([5, 6, 7], _6836, _6554) ? creep
41 Exit: (13) elementAt([5, 6, 7], 0, 5) ? creep
42 Call: (13) _6840 is 0+1 ? creep
43 Exit: (13) 1 is 0+1 ? creep
44 Exit: (12) elementAt([4, 5, 6, 7], 1, 5) ? creep
45 Call: (12) _6846 is 1+1 ? creep
46 Exit: (12) 2 is 1+1 ? creep
47 Exit: (11) elementAt([3, 4, 5, 6, 7], 2, 5) ? creep
48 Call: (11) _6852 is 2+1 ? creep
49 Exit: (11) 3 is 2+1 ? creep
50 Exit: (10) elementAt([2, 3, 4, 5, 6, 7], 3, 5) ? creep
51 Call: (10) _6858 is 3+1 ? creep
52 Exit: (10) 4 is 3+1 ? creep
53 Exit: (9) elementAt([1, 2, 3, 4, 5, 6, 7], 4, 5) ? creep
54 Call: (9) 5 is 4+1 ? creep
55 Exit: (9) 5 is 4+1 ? creep
56 Exit: (8) elementAt([0, 1, 2, 3, 4, 5, 6, 7], 5, 5) ? creep
Line 1 to 5 is perfectly clear. The first rule matches which binds _6836 to 0. The N is N1 + 1 constraint fails and tries the elementAt([_|Tail], N, Element) predicate. This also means that _6836 is no longer bound to 0, right?
Line 7 is what I don't understand. Prolog tries to redo the
elementAt([1, 2, 3, 4, 5, 6, 7], _6836, _6554)
call which results in the call that's made in line 8 which is
elementAt([2, 3, 4, 5, 6, 7], _6836, _6554).
I noted that _6836 which should be N in line 7 get's also used as N1 in line 8. Why does Prolog do that?
These are two completely different variables. The same pattern repeats in line 14-15, 25-26 and 39-40. Eventually it gets the correct element but I really don't understand how.
I think I don't quite understand how the redo works but I'm out of ideas.
Is the N1 (_6836) in trace line 6 the same variable as the N1(_6836) in trace line 7?
Yes, it is the same variable. If you look at the trace you will see that at
6 Redo: (9) elementAt([1, 2, 3, 4, 5, 6, 7], _6044, _5790) ? creep
is source line
elementAt(Tail, N1, Element)
so _6836 is N1
then
7 Call: (10) elementAt([2, 3, 4, 5, 6, 7], _6044, _5790) ? creep
is source line
elementAt([_|Tail], N, Element)
Notice the depth changed from (9) to (10)
so _6836 is N
thus N1 and N are unified but not yet bound. I don't know if that is the correct way to say it, but I am sure I will be corrected if not.
Personally I don't use trace much, I prefer to use these debugging predicates or gtrace when needed.
Related
isgreater([H1|T1],[H2|T2],D):-
H1 > H2,isgreater(T1,T2,['Yes'|D]).
isgreater([H1|T1],[H2|T2],D):-
H1 =< H2,isgreater(T1,T2,['No'|D]).
isgreater([],[],D).
The ideal output should be
{No,No,No,No,Yes}
This is the trace
Call: (10) isgreater([1, 2, 3, 4, 5], [4, 4, 4, 4, 4], _49600) ? creep
Call: (11) 1>4 ? creep
Fail: (11) 1>4 ? creep
Redo: (10) isgreater([1, 2, 3, 4, 5], [4, 4, 4, 4, 4], _49600) ? creep
Call: (11) 1=<4 ? creep
Exit: (11) 1=<4 ? creep
* Call: (11) isgreater([2, 3, 4, 5], [4, 4, 4, 4], ('No'| _49600)) ? creep
Call: (12) 2>4 ? creep
Fail: (12) 2>4 ? creep
* Redo: (11) isgreater([2, 3, 4, 5], [4, 4, 4, 4], ('No'| _49600)) ? creep
Call: (12) 2=<4 ? creep
Exit: (12) 2=<4 ? creep
* Call: (12) isgreater([3, 4, 5], [4, 4, 4], ('No'| 'No'| _49600)) ? creep
Call: (13) 3>4 ? creep
Fail: (13) 3>4 ? creep
* Redo: (12) isgreater([3, 4, 5], [4, 4, 4], ('No'| 'No'| _49600)) ? creep
Call: (13) 3=<4 ? creep
Exit: (13) 3=<4 ? creep
* Call: (13) isgreater([4, 5], [4, 4], ('No'| 'No'| 'No'| _49600)) ? creep
Call: (14) 4>4 ? creep
Fail: (14) 4>4 ? creep
* Redo: (13) isgreater([4, 5], [4, 4], ('No'| 'No'| 'No'| _49600)) ? creep
Call: (14) 4=<4 ? creep
Exit: (14) 4=<4 ? creep
* Call: (14) isgreater([5], [4], ('No'| 'No'| 'No'| 'No'| _49600)) ? creep
Call: (15) 5>4 ? creep
Exit: (15) 5>4 ? creep
* Call: (15) isgreater([], [], ('Yes'| 'No'| 'No'| 'No'| 'No'| _49600)) ? creep
* Exit: (15) isgreater([], [], ('Yes'| 'No'| 'No'| 'No'| 'No'| _49600)) ? creep
* Exit: (14) isgreater([5], [4], ('No'| 'No'| 'No'| 'No'| _49600)) ? creep
* Exit: (13) isgreater([4, 5], [4, 4], ('No'| 'No'| 'No'| _49600)) ? creep
* Exit: (12) isgreater([3, 4, 5], [4, 4, 4], ('No'| 'No'| _49600)) ? creep
* Exit: (11) isgreater([2, 3, 4, 5], [4, 4, 4, 4], ('No'| _49600)) ? creep
Exit: (10) isgreater([1, 2, 3, 4, 5], [4, 4, 4, 4, 4], _49600) ? creep
I miss some points here, but I just can't figure it out.
The program can only return a true value.
I can only append an element in the front of the list.
I can not get D when it is the case isgreater([],[],D).
You can solve the problem as following:
isgreater([H1|T1], [H2|T2], ['Yes'|D]) :- % solution is ['Yes'|D] if
H1 > H2, % H1 is greater than H2 and
isgreater(T1, T2, D). % D is the solution for the small
% instance of the problem
isgreater([H1|T1], [H2|T2], ['No'|D]):- % analogous to the last case
H1 =< H2,
isgreater(T1, T2, D).
isgreater([], [], []). % solution is empty if both lists are empty!
Running example:
?- isgreater([1, 2, 3, 4, 5], [4, 4, 4, 4, 4], A).
A = ['No', 'No', 'No', 'No', 'Yes'] ;
false.
?- isgreater([1, 2, 3, 4, 5], [4, 1, 5, 3, 2], A).
A = ['No', 'Yes', 'No', 'Yes', 'Yes'] ;
false.
?- isgreater([], [], A).
A = [].
Given a number N and a list, I want to enumerate all ways to select numbers from the list so that their sum equals N. I can use numbers from the list multiple times. I thought of logic roughly corresponding to following tree:
I came up with following code:
append([], Y, [Y]). %append[] and Y to get Y.
append([H|X], Y, [H|Z]) :- append(X, Y, Z). % append [H|X] and Y to get [H|Z] if appending X and Y gives Z
ss(0, [], Ans).
ss(N, L, Ans) :-
ss1(N, 0, L, [], Ans).
ss1(N, N1, [], L2, Ans) :-
N == N1,
Ans = L2.
ss1(N, N1, L, L1, Ans) :-
N == N1,
Ans = L2.
ss1(N, N1, L, L1, Ans) :-
[A | B] = L,
N2 is (A+N1),
append(L1, A, L2),
N >= N2,
ss1(N, N2, L, L2, Ans).
ss1(N, N1, L, L1, Ans) :-
[A, B | C] = L,
N2 is (B+N1),
append(L1, B, L2),
N >= N2,
ss1(N, N2, L, L2, Ans).
Running it gives following:
?- ss(20, [5, 8, 13, 10, 2], Ans).
Call: (10) cc(20, [5, 8, 13, 10, 2], _3530) ? creep
Call: (11) cc1(20, 0, [5, 8, 13, 10, 2], [], _3530) ? creep
Call: (12) 20==0 ? creep
Fail: (12) 20==0 ? creep
Redo: (11) cc1(20, 0, [5, 8, 13, 10, 2], [], _3530) ? creep
Call: (12) [5, 8, 13, 10, 2]=[_4130|_4132] ? creep
Exit: (12) [5, 8, 13, 10, 2]=[5, 8, 13, 10, 2] ? creep
Call: (12) _4282 is 5+0 ? creep
Exit: (12) 5 is 5+0 ? creep
Call: (12) append([], 5, _4374) ? creep
Exit: (12) append([], 5, [5]) ? creep
Call: (12) 20>=5 ? creep
Exit: (12) 20>=5 ? creep
Call: (12) cc1(20, 5, [5, 8, 13, 10, 2], [5], _3530) ? creep
Call: (13) 20==5 ? creep
Fail: (13) 20==5 ? creep
Redo: (12) cc1(20, 5, [5, 8, 13, 10, 2], [5], _3530) ? creep
Call: (13) [5, 8, 13, 10, 2]=[_4676|_4678] ? creep
Exit: (13) [5, 8, 13, 10, 2]=[5, 8, 13, 10, 2] ? creep
Call: (13) _4828 is 5+5 ? creep
Exit: (13) 10 is 5+5 ? creep
Call: (13) append([5], 5, _4920) ? creep
Call: (14) append([], 5, _4910) ? creep
Exit: (14) append([], 5, [5]) ? creep
Exit: (13) append([5], 5, [5, 5]) ? creep
Call: (13) 20>=10 ? creep
Exit: (13) 20>=10 ? creep
Call: (13) cc1(20, 10, [5, 8, 13, 10, 2], [5, 5], _3530) ? creep
Call: (14) 20==10 ? creep
Fail: (14) 20==10 ? creep
Redo: (13) cc1(20, 10, [5, 8, 13, 10, 2], [5, 5], _3530) ? creep
Call: (14) [5, 8, 13, 10, 2]=[_5316|_5318] ? creep
Exit: (14) [5, 8, 13, 10, 2]=[5, 8, 13, 10, 2] ? creep
Call: (14) _5468 is 5+10 ? creep
Exit: (14) 15 is 5+10 ? creep
Call: (14) append([5, 5], 5, _5560) ? creep
Call: (15) append([5], 5, _5550) ? creep
Call: (16) append([], 5, _5600) ? creep
Exit: (16) append([], 5, [5]) ? creep
Exit: (15) append([5], 5, [5, 5]) ? creep
Exit: (14) append([5, 5], 5, [5, 5, 5]) ? creep
Call: (14) 20>=15 ? creep
Exit: (14) 20>=15 ? creep
Call: (14) cc1(20, 15, [5, 8, 13, 10, 2], [5, 5, 5], _3530) ? creep
Call: (15) 20==15 ? creep
Fail: (15) 20==15 ? creep
Redo: (14) cc1(20, 15, [5, 8, 13, 10, 2], [5, 5, 5], _3530) ? creep
Call: (15) [5, 8, 13, 10, 2]=[_6050|_6052] ? creep
Exit: (15) [5, 8, 13, 10, 2]=[5, 8, 13, 10, 2] ? creep
Call: (15) _6202 is 5+15 ? creep
Exit: (15) 20 is 5+15 ? creep
Call: (15) append([5, 5, 5], 5, _6294) ? creep
Call: (16) append([5, 5], 5, _6284) ? creep
Call: (17) append([5], 5, _6334) ? creep
Call: (18) append([], 5, _6384) ? creep
Exit: (18) append([], 5, [5]) ? creep
Exit: (17) append([5], 5, [5, 5]) ? creep
Exit: (16) append([5, 5], 5, [5, 5, 5]) ? creep
Exit: (15) append([5, 5, 5], 5, [5, 5, 5, 5]) ? creep
Call: (15) 20>=20 ? creep
Exit: (15) 20>=20 ? creep
Call: (15) cc1(20, 20, [5, 8, 13, 10, 2], [5, 5, 5, 5], _3530) ? creep
Call: (16) 20==20 ? creep
Exit: (16) 20==20 ? creep
Call: (16) true ? creep
Exit: (16) true ? creep
Exit: (15) cc1(20, 20, [5, 8, 13, 10, 2], [5, 5, 5, 5], _3530) ? creep
Exit: (14) cc1(20, 15, [5, 8, 13, 10, 2], [5, 5, 5], _3530) ? creep
Exit: (13) cc1(20, 10, [5, 8, 13, 10, 2], [5, 5], _3530) ? creep
Exit: (12) cc1(20, 5, [5, 8, 13, 10, 2], [5], _3530) ? creep
Exit: (11) cc1(20, 0, [5, 8, 13, 10, 2], [], _3530) ? creep
Exit: (10) cc(20, [5, 8, 13, 10, 2], _3530) ? creep
true .
As you can see, it forms the list [5,5,5,5] which sums to 20. But instead of returning it, it returns true, despite we equate it with Ans. It also need to return sets: [5,5,10],[10,10],[2,2,2,2,2,10],[2,8,10],[2,2,2,2,2,2,8],[2,2,8,8].
Why so? Also is there any simpler logic possible?
(ref for append())
phew, there is a lot to say, so let's start:
your definition of append/3 is pretty unorthodox and in some systems, you are not allowed to redefine append/3, which is in-built (and differs from your definition), so let's change that to append2/3 for now:
append2([], Y, [Y]).
append2([H|X], Y, [H|Z]) :- append2(X, Y, Z).
You don't need ss(0, [], Ans), so let's skip this.
We keep:
ss(N, L, Ans) :-
ss1(N, 0, L, [], Ans).
Let's have a look at the next two clauses, your base clauses for ss1:
ss1(N, N1, [], L2, Ans) :-
N == N1,
Ans = L2.
ss1(N, N1, L, L1, Ans) :-
N == N1,
Ans = L2.
In the second clause - where is the prolog system supposed to take L2 from? Also, we do not need two clauses to express what your aiming at, one suffices:
ss1(N, N, _, L1, L1).
We leave the next two clauses for a second (only having renamed append/3):
ss1(N, N1, L, L1, Ans) :-
[A | B] = L,
N2 is (A+N1),
append2(L1, A, L2),
N >= N2,
ss1(N, N2, L, L2, Ans).
ss1(N, N1, L, L1, Ans) :-
[A, B | C] = L,
N2 is (B+N1),
append2(L1, B, L2),
N >= N2,
ss1(N, N2, L, L2, Ans).
So, we now have the program
append2([], Y, [Y]).
append2([H|X], Y, [H|Z]) :- append2(X, Y, Z).
ss(N, L, Ans) :- ss1(N, 0, L, [], Ans).
ss1(N, N, _, L1, L1). % clause 1 for ss1
ss1(N, N1, L, L1, Ans) :- % clause 2 for ss1
[A | B] = L,
N2 is (A+N1),
append2(L1, A, L2),
N >= N2,
ss1(N, N2, L, L2, Ans).
ss1(N, N1, L, L1, Ans) :- %clause 3 for ss1
[A, B | C] = L,
N2 is (B+N1),
append2(L1, B, L2),
N >= N2,
ss1(N, N2, L, L2, Ans).
Now, we get:
?- ss(20, [5, 8, 13, 10, 2], Ans).
Ans = [5, 5, 5, 5] ;
We also get:
?- ss(0, [5, 8, 13, 10, 2], Ans).
Ans = [] ;
We even get:
?- ss(4,[1,2],Ans).
Ans = [1, 1, 1, 1] ;
Ans = [1, 1, 2] ;
Ans = [1, 2, 1] ;
Ans = [2, 1, 1] ;
Ans = [2, 2] ;
So, that's way progress. But the problem is, that in clauses 2 and 3 for ss1/5, we only look at the first elements of the list to pick from, so we still have to solve this ;-)
One solution is to replace clauses 2 and 3 for ss1/5 by one single clause:
ss1(N, N1, L, L1, Ans) :-
member(A,L),
N2 is (A+N1),
append2(L1, A, L2),
N >= N2,
ss1(N, N2, L, L2, Ans).
member/2 is built-in in many prolog systems, if it is not in yours, it is easy to define.
Now, we still have a problem if 0 is not the last member of the list - then we get into an endless loop, for example
?- ss(1, [0,1],Ans).
?- ss(2, [3,0,1],Ans).
Let's therefore ignore 0s and only enumerate sums of integers >0.
From your comments, I also get that you want to enumerate each multiset only once. Here's a solution:
ss(N, L, Ans) :-
sort(L,S),
reverse(S,R),
ss1(N, 0, R, [], Ans).
ss1(N, N, _, L, L) :- !.
ss1(N, N1, [H|T], L1, Ans) :-
H > 0,
N2 is H+N1,
N>=N2,
ss1(N, N2, [H|T], [H|L1], Ans).
ss1(N, N1, [_|T], L1, Ans) :-
ss1(N, N1, T, L1, Ans).
If you want to allow 0s or negative integers in the list, please indicate in your comments - then this needs to be fixed.
To your inital question, we now get:
?- ss(20, [5, 8, 13, 10, 2], Ans).
Ans = [2, 5, 13] ;
Ans = [10, 10] ;
Ans = [2, 8, 10] ;
Ans = [5, 5, 10] ;
Ans = [2, 2, 2, 2, 2, 10] ;
Ans = [2, 2, 8, 8] ;
Ans = [2, 5, 5, 8] ;
Ans = [2, 2, 2, 2, 2, 2, 8] ;
Ans = [5, 5, 5, 5] ;
Ans = [2, 2, 2, 2, 2, 5, 5] ;
Ans = [2, 2, 2, 2, 2, 2, 2, 2, 2|...] ;
false.
Since the last answer is too long to be shown this way, we can also ask:
?- ss(20, [5, 8, 13, 10, 2], Ans), write(Ans), nl,fail.
[2,5,13]
[10,10]
[2,8,10]
[5,5,10]
[2,2,2,2,2,10]
[2,2,8,8]
[2,5,5,8]
[2,2,2,2,2,2,8]
[5,5,5,5]
[2,2,2,2,2,5,5]
[2,2,2,2,2,2,2,2,2,2]
false.
I have that previous question about this quicksort here.The prolog code for quicksort:
gt(X,Y):- X #>Y.
conc([],List, List).
conc([Head|Tail], List1, [Head|List2]):- conc(Tail, List1, List2).
quicksort([],[]).
quicksort([X|Tail],Sorted):-
split(X,Tail,Small,Big),
quicksort(Small,SortedSmall),
quicksort(Big,SortedBig),
conc(SortedSmall,[X|SortedBig],Sorted).
[1]split(X,[],[],[]).
[2]split(X,[Y|Tail],[Y|Small],Big):-
gt(X,Y),!,
split(X,Tail,Small,Big).
[3]split(X,[Y|Tail],Small,[Y|Big]):-
split(X,Tail,Small,Big).
The array for example is [3,2,4,1,5]. This is the first part of the trace route:
?- trace, quicksort([3,2,4,1,5], Sorted).
1 Call: (7) quicksort([3, 2, 4, 1, 5], _G4136) ? creep
2 Call: (8) split(3, [2, 4, 1, 5], _G4269, _G4270) ? creep
3 Call: (9) gt(3, 2) ? creep
4 Call: (10) 3#>2 ? creep
5 Exit: (10) 3#>2 ? creep
6 Exit: (9) gt(3, 2) ? creep
7 Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ? creep
8 Call: (10) gt(3, 4) ? creep
9 Call: (11) 3#>4 ? creep
10 Fail: (11) 3#>4 ? creep
11 Fail: (10) gt(3, 4) ? creep
12 Redo: (9) split(3, [4, 1, 5], _G4261, _G4273) ? creep
13 Call: (10) split(3, [1, 5], _G4261, _G4264) ? creep
At the line 2, prolog apply the rule [2] of split and we have Call: (8) split(3, [2, 4, 1, 5], _G4269, _G4270) and we have _G4269 is [2|Small] and _G4270 is Big.
It then compare 3 and 2, gt(3,2) return true and it does not execute the cut. Continue with split(X,Tail,Small,Big) which is Call: (9) split(3, [4, 1, 5], _G4261, _G4273)
If the gt(X,Y) return false, prolog will execute the cut and then apply the rule [3] of the split (line 11-12).
Am I doing right and why the last variable has become a new one (_G4237 instead of _G4270)? Because in the code I thought it is the same.
Anyone could help me clear things out?
Many thanks!
To be precise: your question concerns this part of the trace:
2 Call: (8) split(3, [2, 4, 1, 5], _G4269, _G4270) ? creep
3 Call: (9) gt(3, 2) ? creep
4 Call: (10) 3#>2 ? creep
5 Exit: (10) 3#>2 ? creep
6 Exit: (9) gt(3, 2) ? creep
7 Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ? creep
which corresponds to the call to:
split(X,[Y|Tail],[Y|Small],Big):-
gt(X,Y),!,
split(X,Tail,Small,Big).
and you are right there is no VISIBLE reason to obtain different variables since the same variable Big is used. I admit it is confusing. And, you could obtain the same variable. This can be shown calling directly split(3, [2, 4, 1, 5], S, B) the trace is then (with swi v6.6.6):
[trace] ?- split(3, [2, 4, 1, 5], S, B).
Call: (6) split(3, [2, 4, 1, 5], _G4537, _G4538) ? creep
Call: (7) gt(3, 2) ? creep
Call: (8) 3#>2 ? creep
Exit: (8) 3#>2 ? creep
Exit: (7) gt(3, 2) ? creep
Call: (7) split(3, [4, 1, 5], _G4630, _G4538) ? creep
And the same variable is used (_G4538).
However, the interpreter can have INVISIBLE reason to unify a variable X with a brand new one Y and use Yinstead of X in subsequent computations. It is what occurs in your example. You can use the command g (goals) when debugging to obtain a backtrace, which will show the current stack trace with current variable bindings. Returning to your example, when you reach
7 Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ?
type g to have a backtrace and you obtain something like:
[9] split(3, [4, 1, 5], _G4261, _G4273)
[8] split(3, [2, 4, 1, 5], [2|_G4261], _G4273)
[7] quicksort([3, 2, 4, 1, 5], _G4136)
Call: (9) split(3, [4, 1, 5], _G4261, _G4273) ?
And now you can see that _G4273 is the same variable in depth [8] and [9].
I want to calculate , in two lists (same lenght), the number of elements that are equal and in the same position.
For example:
Lets say we have the lists A = [3,6,7,9] and B = [2,6,4,9], i want to be printed in the screen the message, "2 bulls found".
So far i have made this:
bulls([],[]).
bulls([Ha|Ta],[Hb|Tb]) :-
Ha = Hb,
writeln('bull found'),
bulls(Ta,Tb);
bulls(Ta,Tb).
Every time an element that exists in the same place in both lists, the message 'bull found' is printed.
And in my mind i want to make something like this:
bulls([],[],_).
bulls([Ha|Ta],[Hb|Tb],Counter) :-
Ha = Hb,
NewCounter is Counter + 1,
bulls(Ta,Tb,NewCounter);
bulls(Ta,Tb,NewCounter).
bulls(List1,List2):- bulls(List1,List2,0).
bulls is called from another rule that passes the lists two it.
How do i make it so it prints the value of 'bulls' to the screen. Any help?
Edit
So after Suki's post, i made this test program testing 2 lists:
bulls([],[],X), write(X), write('bulls found'),fail.
bulls([Ha|Ta],[Hb|Tb],Counter) :-
Ha = Hb,
NewCounter is Counter + 1,
bulls(Ta,Tb,NewCounter);
bulls(Ta,Tb,NewCounter).
check(List1,List2):-
bulls(List1,List2,0).
start:-
A=[1,1,1,1],
B=[2,1,2,1],
writeln(A),writeln(B),
check(A,B).
and i get this result
1 ?- start.
[1,1,1,1]
[2,1,2,1]
ERROR: bulls/3: Arguments are not sufficiently instantiated
what am i doing wrong?
Regarding your edited program:
The first clause is not a clause, it's a goal! It should look like this:
bulls([],[],X) :- write(X), write(' bulls found').
You should drop the fail, btw.
In the second clause, you need to use "if-then-else", and use Counter instead of NewCounter in the "else"-branch:
bulls([Ha|Ta],[Hb|Tb],Counter) :-
(
Ha == Hb
->
NewCounter is Counter + 1,
bulls(Ta,Tb,NewCounter)
;
bulls(Ta,Tb,Counter)
).
Assuming that the predicates findall, length, nth0 exist in your prolog implementation:
(The trace below is from swi-prolog)
A = [3,6,7,9],
B = [2,6,4,9],
findall(Y, ((nth0(X, A, Y), nth0(X, B, Y))), Y),
length(Y, LenY),
write(LenY), write(' Bulls Found').
[trace] ?- A = [3,6,7,9],
B = [2,6,4,9],
findall(Y, ((nth0(X, A, Y), nth0(X, B, Y))), Y),
length(Y, LenY),
write(LenY), write(' Bulls Found').
Call: (7) _G2814=[3, 6, 7, 9] ? creep
Exit: (7) [3, 6, 7, 9]=[3, 6, 7, 9] ? creep
Call: (7) _G2829=[2, 6, 4, 9] ? creep
Exit: (7) [2, 6, 4, 9]=[2, 6, 4, 9] ? creep
^ Call: (7) findall(_G2834, (nth0(_G2832, [3, 6, 7, 9], _G2834), nth0(_G2832, [2, 6, 4, 9], _G2834)), _G2834) ? creep
Call: (13) lists:nth0(_G2832, [3, 6, 7, 9], _G2834) ? creep
Exit: (13) lists:nth0(0, [3, 6, 7, 9], 3) ? creep
Call: (13) lists:nth0(0, [2, 6, 4, 9], 3) ? creep
Fail: (13) lists:nth0(0, [2, 6, 4, 9], 3) ? creep
Redo: (13) lists:nth0(_G2832, [3, 6, 7, 9], _G2834) ? creep
Exit: (13) lists:nth0(1, [3, 6, 7, 9], 6) ? creep
Call: (13) lists:nth0(1, [2, 6, 4, 9], 6) ? creep
Exit: (13) lists:nth0(1, [2, 6, 4, 9], 6) ? creep
Redo: (13) lists:nth0(_G2832, [3, 6, 7, 9], _G2834) ? creep
Exit: (13) lists:nth0(2, [3, 6, 7, 9], 7) ? creep
Call: (13) lists:nth0(2, [2, 6, 4, 9], 7) ? creep
Fail: (13) lists:nth0(2, [2, 6, 4, 9], 7) ? creep
Redo: (13) lists:nth0(_G2832, [3, 6, 7, 9], _G2834) ? creep
Exit: (13) lists:nth0(3, [3, 6, 7, 9], 9) ? creep
Call: (13) lists:nth0(3, [2, 6, 4, 9], 9) ? creep
Exit: (13) lists:nth0(3, [2, 6, 4, 9], 9) ? creep
^ Exit: (7) findall([6, 9], user: (nth0(_G2832, [3, 6, 7, 9], [6, 9]), nth0(_G2832, [2, 6, 4, 9], [6, 9])), [6, 9]) ? creep
Call: (7) length([6, 9], _G2848) ? creep
Exit: (7) length([6, 9], 2) ? creep
Call: (7) write(2) ? creep
2
Exit: (7) write(2) ? creep
Call: (7) write(' Bulls Found') ? creep
Bulls Found
Exit: (7) write(' Bulls Found') ? creep
A = [3, 6, 7, 9],
B = [2, 6, 4, 9],
Y = [6, 9],
LenY = 2.
So i have an assignment in which i have to make a guessing game (bulls and cows).
Firstly i made i little program where you enter two numbers and it checks
if they have the same length and then if they are equal.
*The numbers have have to be in lists, in order to be able to give in every guess the number of bulls and cows (see the rules of the game).
equal([],[]).
equal([Ha|Ta],[Hb|Tb]) :-
Ha = Hb, equal(Ta,Tb).
check_length(List1,List2):-
same_length(List1,List2),writeln('The Lists have the same length!').
check_equality(List1,List2):-
equal(List1,List2),writeln('The Lists are equal!').
start:-
write('give 1st list:'), read(X),atom_chars(X, List1),
write('give 2nd list:'), read(Y),atom_chars(Y, List2),
check_length(List1,List2),
check_equality(List1,List2).
So far so good. It works fine. Then i went on to the next step and altered it, so it generates a list with 4 random integers and then it waits for the user to make a guess and compares the two lists like before. *Obviously i print the generated number to the screen in order to know if the program works ok.
start:-
A is random(9),
B is random(9),
C is random(9),
D is random(9),
List2=[A,B,C,D],
write('Generated number:'),writeln(List2),
write('Make a guess:'), read(Guess),atom_chars(Guess, List1),
nl,
check_length(List1,List2),
check_equality(List1,List2).
The problem is that this time even if you type the right number, the program does figure out if the lists (numbers) have the same length but fails in equality check.
What am i doing wrong?
Thanks in advance.
Here is the trace from a run:
[trace] 42 ?- start.
Call: (6) start ? creep
^ Call: (7) _G537 is random(9) ? creep
^ Exit: (7) 6 is random(9) ? creep
^ Call: (7) _G539 is random(9) ? creep
^ Exit: (7) 6 is random(9) ? creep
^ Call: (7) _G541 is random(9) ? creep
^ Exit: (7) 1 is random(9) ? creep
^ Call: (7) _G543 is random(9) ? creep
^ Exit: (7) 4 is random(9) ? creep
Call: (7) _G555=[6, 6, 1, 4] ? creep
Exit: (7) [6, 6, 1, 4]=[6, 6, 1, 4] ? creep
Call: (7) write('Generated number:') ? creep
Generated number:
Exit: (7) write('Generated number:') ? creep
Call: (7) writeln([6, 6, 1, 4]) ? creep
[6,6,1,4]
Exit: (7) writeln([6, 6, 1, 4]) ? creep
Call: (7) write('Make a guess:') ? creep
Make a guess:
Exit: (7) write('Make a guess:') ? creep
Call: (7) read(_G555) ? creep
| 6614.
Exit: (7) read(6614) ? creep
Call: (7) atom_chars(6614, _G556) ? creep
Exit: (7) atom_chars(6614, ['6', '6', '1', '4']) ? creep
Call: (7) nl ? creep
Exit: (7) nl ? creep
Call: (7) check_length(['6', '6', '1', '4'], [6, 6, 1, 4]) ? creep
Call: (8) length(['6', '6', '1', '4'], _G568) ? creep
Exit: (8) length(['6', '6', '1', '4'], 4) ? creep
Call: (8) length([6, 6, 1, 4], 4) ? creep
Exit: (8) length([6, 6, 1, 4], 4) ? creep
Call: (8) writeln('The Lists have the same length!') ? creep
The Lists have the same length!
Exit: (8) writeln('The Lists have the same length!') ? creep
Exit: (7) check_length(['6', '6', '1', '4'], [6, 6, 1, 4]) ? creep
Call: (7) check_equality(['6', '6', '1', '4'], [6, 6, 1, 4]) ? creep
Call: (8) equal(['6', '6', '1', '4'], [6, 6, 1, 4]) ? creep
Call: (9) '6'=6 ? creep
Fail: (9) '6'=6 ? creep
Fail: (8) equal(['6', '6', '1', '4'], [6, 6, 1, 4]) ? creep
Fail: (7) check_equality(['6', '6', '1', '4'], [6, 6, 1, 4]) ? creep
Fail: (6) start ? creep
false.
the important part is this:
Call: (9) '6'=6 ? creep
Fail: (9) '6'=6 ? creep
so the problem is that the char '6' is not equal with the number 6
another issue is that zeroes in the beginning will be deleted
23 ?- atom_chars(0042,L).
L = ['4', '2'].
so I would suggest to get rid of atom_chars/2 and do something else; read the four numbers one by one or split the number manually
In your second code, List2 is a list of numbers. List1 however, as generated by atom_chars/2, is a list of quoted atoms. Numbers and atoms are not the same thing. You will have to convert either one of the lists into the type of the other (e.g., using atom_number/2) before your equality check will succeed.