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].
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 = [].
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.
I have some doubt about how work the following implementation of BubbleSort algorithm in Prolog.
I have very clear how BubbleSort algorithm work so my doubt is only related to the Prolog first order logic and declarative interpretation.
This is my code:
bubbleSort(List, SortedList) :- swap(List, List1),
!,
bubbleSort(List1, SortedList).
bubbleSort(SortedList, SortedList).
/* swap predicate swap the two element if X come after Y in lexicographical order */
swap([X,Y|Tail], [Y,X|Tail]) :- X #> Y.
/* If it is not true that X come after Y in lexicographical order let the head in its
original position and call the swap predicate on the sublist */
swap([Z|Tail], [Z|Tail1]) :- swap(Tail, Tail1).
So I have some doubt about declarative interpretation of this program:
The core of the program is the bubbleSort/2 predicate that perform the scansion of List in which are performed eventual swap of adjacent elements.
So swap/2 predicate work like a procedural if:
1) IF the first element in the sublist (X) follow the second element in the sublist (Y) in the lexicographical order it is not good, so perform the swap.
2) Otherwise X and Y are in the right order and try to execute te swap on the sublist Tail
So for example if I perform the following query:
[trace] ?- bubbleSort([3,2,1], Sorted).
I obtain:
Call: (7) bubbleSort([3, 2, 1], _G399) ? creep
Call: (8) swap([3, 2, 1], _G478) ? creep
Call: (9) 3#>2 ? creep
Exit: (9) 3#>2 ? creep
Exit: (8) swap([3, 2, 1], [2, 3, 1]) ? creep
Call: (8) bubbleSort([2, 3, 1], _G399) ? creep
Here call the first version of bubbleSort/2 on the original list. To be TRUE call the first version of swap/2 predicate that check if the first two elements of the list are not in lexicographical order each other, this fact is TRUE so swap these elements. Now that swap/2 predicate is verified, come back by backtracking and (to satisfy bubbleSort/2) call again bubbleSort2 saying now that the original list to order is the list after the swap (the list in which the first and the second element are swapped)
So call again bubbleSort and happen:
Call: (8) bubbleSort([2, 3, 1], _G399) ? creep
Call: (9) swap([2, 3, 1], _G484) ? creep
Call: (10) 2#>3 ? creep
Fail: (10) 2#>3 ? creep
Redo: (9) swap([2, 3, 1], _G484) ? creep
Call: (10) swap([3, 1], _G480) ? creep
Call: (11) 3#>1 ? creep
Exit: (11) 3#>1 ? creep
Exit: (10) swap([3, 1], [1, 3]) ? creep
Exit: (9) swap([2, 3, 1], [2, 1, 3]) ? creep
So now it try to satisfy swap/2 on the list [2,3,1] but now this is not true that the first two elements are not in lexicographical order each other, so the first version of swap/2 predicate fail, so it use the second version that simply call swap/2 on the sublist **[3,1] where it is true that 3 don't follow 1, so swap it and I obtain the [1,3] list.
Here I have the first doubt: after this swap on this sublist (from [3,1] to [1,3]) I obtain the list: [2, 1, 3] in this line:
Exit: (9) swap([2, 3, 1], [2, 1, 3]) ? creep
why? is this because after have satisfied swap(Tail, Tail1) predicate:
swap([Z|Tail], [Z|Tail1]) :- swap(Tail, Tail1).
I have that Tail1 is [1,3] so Z was the old head 2 and [Z|Tail1] is [2,1,3] ?
However, now it is end the first scansion of the bubble sort algorithm that have take the "bigger" element at the end of the list
The execution continues in the same way but I have a doubt about the end of the program execution that is:
Redo: (10) bubbleSort([1, 2, 3], _G399) ? creep
Exit: (10) bubbleSort([1, 2, 3], [1, 2, 3]) ? creep
Exit: (9) bubbleSort([2, 1, 3], [1, 2, 3]) ? creep
Exit: (8) bubbleSort([2, 3, 1], [1, 2, 3]) ? creep
Exit: (7) bubbleSort([3, 2, 1], [1, 2, 3]) ? creep
Sorted = [1, 2, 3].
So at the end call the bubbleSort/2 predicate on an ordered List by:
Redo: (10) bubbleSort([1, 2, 3], _G399) ? creep
where [1,2,3] is List1.
Now I am in the second version of bubbleSort/2 predicate, this one:
bubbleSort(SortedList, SortedList).
where the list to sort and the sorted list is the same (so it means that the original list is totatly sorted).
So what is this? the base case that, once verified, say that the program execution have to end?
So execute backtracking to say that all the previous bubbleSort/2 are verified, untill reach the first bubbleSort/2 call and say that this is vierified and unify Sorted with [1,2,3] list
Is my reasoning correct? Are there a more declarative interpretation of this?
I think the key to understand this algorithm it's the fact that swap/2 fails when the list is sorted - there is no match on empty list.
From here the necessity of the second bubbleSort/2 rule.
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.