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.
Related
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].
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!
I am trying to write a simple translator, where you enter a list of numerical numbers and it returns their string values like so :
translate([1,2,3], X).
X=[one, two, three].
The code I have written works...except it returns an empty list. Here is my code and the trace:
means(1, one).
means(2, two).
means(3, three).
means(4, four).
means(5, five).
means(6, six).
means(7, seven).
means(8, eight).
means(9, nine).
means(10, ten).
translate([], X).
translate([H|T], []):-
means(H, X),
translate(T, X).
translate([H|T], X):-
means(H, Y),
translate(T, [X|Y]).
[trace] 1 ?- translate([1,2,3], X).
Call: (6) translate([1, 2, 3], _G2219) ? creep
Call: (7) means(1, _G2301) ? creep
Exit: (7) means(1, one) ? creep
Call: (7) translate([2, 3], one) ? creep
Call: (8) means(2, _G2301) ? creep
Exit: (8) means(2, two) ? creep
Call: (8) translate([3], [one|two]) ? creep
Call: (9) means(3, _G2304) ? creep
Exit: (9) means(3, three) ? creep
Call: (9) translate([], [[one|two]|three]) ? creep
Exit: (9) translate([], [[one|two]|three]) ? creep
Exit: (8) translate([3], [one|two]) ? creep
Exit: (7) translate([2, 3], one) ? creep
Exit: (6) translate([1, 2, 3], []) ? creep
X = [] .
My other question is: why is my list concatenating as [[one|two]|three]? instead of [one, two, three]?
Thanks,
You get empty list because of translate([H|T], []) clause.
The whole program (except means facts) can be just this simple:
translate([], []).
translate([NumH | NumT], [WordH | WordT]) :-
means(NumH, WordH),
translate(NumT, WordT).
Doing it manually Sergey's way is good practice, but you can simplify even further with maplist/3:
translate(Numbers, Words) :- maplist(means, Numbers, Words).
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.
This is my first idea:
perm([X|Y],Z) :- takeout(X,Z,W), perm(Y, W).
perm([],[]).
When I tried to run -? perm([1, 2, 3], P)., it showed a stack overflow problem.
But if we change the order of the two statements, it will work.
perm([X|Y],Z) :- perm(Y, W), takeout(X,Z,W).
perm([],[]).
Why? I am a Prolog beginner, please help.
The takeout/3 you refer to is commonly known as select(X, Xs0, Xs)
Here is another definition - to illustrate an uncommon usage of DCGs.
perm(Xs,Ys) :-
phrase(perm(Xs),[],Ys).
perm([]) --> [].
perm([X|Xs]) --> perm(Xs), ins(X).
ins(X),[X] --> [].
ins(X),[Y] --> [Y], ins(X).
Well, your takeout predicate may look like that:
takeout( X, [X|R], R ).
takeout( X, [F|R], [F|S] ) :-
takeout( X, R, S ).
SWI-Prolog has a useful predicate named trace.
In first case:
X = [1, 2, 3] ;
Redo: (10) takeout(3, _G477, _G485) ? creep
Call: (11) takeout(3, _G480, _G483) ? creep
Exit: (11) takeout(3, [3|_G483], _G483) ? creep
Exit: (10) takeout(3, [_G479, 3|_G483], [_G479|_G483]) ? creep
Call: (10) perm([], [_G479|_G483]) ? creep
Fail: (10) perm([], [_G479|_G483]) ? creep
Redo: (11) takeout(3, _G480, _G483) ? creep
Call: (12) takeout(3, _G486, _G489) ? creep
Exit: (12) takeout(3, [3|_G489], _G489) ? creep
Exit: (11) takeout(3, [_G485, 3|_G489], [_G485|_G489]) ? creep
Exit: (10) takeout(3, [_G479, _G485, 3|_G489], [_G479, _G485|_G489]) ? creep
Call: (10) perm([], [_G479, _G485|_G489]) ? creep
Fail: (10) perm([], [_G479, _G485|_G489]) ? creep
Redo: (12) takeout(3, _G486, _G489) ? creep
Call: (13) takeout(3, _G492, _G495) ? creep
Exit: (13) takeout(3, [3|_G495], _G495) ? creep
Exit: (12) takeout(3, [_G491, 3|_G495], [_G491|_G495]) ? creep
Exit: (11) takeout(3, [_G485, _G491, 3|_G495], [_G485, _G491|_G495]) ? creep
Exit: (10) takeout(3, [_G479, _G485, _G491, 3|_G495], [_G479, _G485, _G491|_G495]) ? creep
Call: (10) perm([], [_G479, _G485, _G491|_G495]) ? creep
Fail: (10) perm([], [_G479, _G485, _G491|_G495]) ? creep
Redo: (13) takeout(3, _G492, _G495) ? creep
Call: (14) takeout(3, _G498, _G501) ? creep
Exit: (14) takeout(3, [3|_G501], _G501) ? creep
Exit: (13) takeout(3, [_G497, 3|_G501], [_G497|_G501]) ? creep
Exit: (12) takeout(3, [_G491, _G497, 3|_G501], [_G491, _G497|_G501]) ? creep
Exit: (11) takeout(3, [_G485, _G491, _G497, 3|_G501], [_G485, _G491, _G497|_G501]) ? creep
In second case:
X = [1, 2, 3] ;
Redo: (8) takeout(1, _G451, [2, 3]) ? creep
Call: (9) takeout(1, _G532, [3]) ? creep
Exit: (9) takeout(1, [1, 3], [3]) ? creep
Exit: (8) takeout(1, [2, 1, 3], [2, 3]) ? creep
Exit: (7) perm([1, 2, 3], [2, 1, 3]) ? creep
So, the order of predicate enumeration is actually important. In first case you produced a lot of states with unknown values. It will be a good idea (as possible) to take a list of paper, running trace and drawing what's really going on.
But in brief, in first case you're producing a lot of unknown variables coated with the takeout fact, which cannot be matched with perm.
Prolog uses SLD resolution and thus order of clauses and order of literals within a clause do make a difference. Basically the engine tries to resolve clause heads by searching top-to-bottom in a depth-first fashion. In other words, there is a procedural semantics on the top of the declarative semantics. This distinction sometimes confuses beginners but, on the other hand, it is the key reason why Prolog is truly a programming language (i.e. Turing complete).
your base case perm([],[]) needs to appear first, otherwise it will keep descending into the perm predicate until you run out of stack space. keep that in mind for future predicates too, its very important in prolog.
Also, you should probably switch up the order of perm & takeout in the other predicate.