PreOrder Tree Traversal in Prolog - prolog

I have this Prolog predicate for PreOrder traversal of a tree:
preOrder(nil, []).
preOrder(node(X, nil, nil), [X]).
preOrder(node(X, L, _), [X|T]) :- preOrder(L, T).
preOrder(node(X, _, R), [X|T]) :- preOrder(R, T).
The problem is, it returns an incomplete list. For example, I get:
?- preOrder(node(1, node(2, node(3,nil,nil), node(4,nil,nil)), node(5,nil,nil)), L).
L = [1,2,3]
When it should be L=[1,2,3,4,5].
Why is it stopping short?

Look at the answers Prolog produces. It's not a single one:
?- preOrder(node(1,node(2,node(3,nil,nil),node(4,nil,nil)),node(5,nil,nil)),L).
L = [1,2,3]
; L = [1,2,3]
; L = [1,2,3]
; L = [1,2,4]
; L = [1,2,4]
; L = [1,2,4]
; L = [1,5]
; L = [1,5]
; L = [1,5]
; false.
Each of your rules describes some part independently of the others. But you need to describe them all together.
The best way to solve this is to use DCGs

It is stopping short because you have two recursive clauses, each one goes just to one side of the tree.
You also have two base cases although the second one is not needed.
So you'd remove the second clause and join the two recursive clauses in only one clause which appends the results from both branches.
E.g.:
preOrder(nil, []).
preOrder(node(X, L, R), [X|T]) :-
preOrder(L, LT),
append(LT, RT, T),
preOrder(R, RT).
You can also use an accumulator for the traversal:
preOrder(Tree, List):-
preOrder(Tree, [], RList),
reverse(RList, List).
preOrder(nil, List, List).
preOrder(node(X, L, R), List, NList) :-
preOrder(L, [X|List], MList),
preOrder(R, MList, NList).
Note that as one commenter said, these definitions for preOrder no not work right to generate trees given a traversal.
You may want to use DCGs to define a procedure that will be reversible, internally using open lists:
preOrder(nil)-->[].
preOrder(node(X, L, R))-->[X], preOrder(L), preOrder(R).
And you would call it using phrase/2:
?- phrase(preOrder(node(1, node(2, node(3,nil,nil), node(4,nil,nil)), node(5,nil,nil))), L).
L = [1, 2, 3, 4, 5].

Related

I cant understand how the function subset(X,Y) works

Can somebody to explain me this code? I try for hours to understand but i can't understand this...
subset([],[]).
subset([X|L],[X|S]) :- subset(L,S).
subset(L, [_|S]) :- subset(L,S).
Imagine that you have a list [1,4], then there are four possible solutions: [1,4], [1], [4], and [], so if you call subset(L, [1,4]), we get:
?- subset(L, [1,4]).
L = [1, 4] ;
L = [1] ;
L = [4] ;
L = [].
The Prolog predicate returns for an empty list an empty list, which is indeed the only sublist we can generate:
sublist([], []).
for a sublist with at least one element X there are each time two possibilities: include X in the result, or do not include X in the result. In both cases we recurse on the tail of the list. The tail thus contains the remaining elements, and for each of these elements, there is again a decision point whether to include these elements or not.
In pseudo-code, an evaluation tree could thus look like:
subset(L, [1,4]) :-
subset([1|L], [1|S]) :-
subset([4|L], [1|S]) :-
subset([], []). % outer L=[1,4]
subset(L, [1|S]) :-
subset([], []). % outer L=[1]
subset(L, [1|S]) :-
subset([4|L], [1|S]) :-
subset([], []). % outer L=[4]
subset(L, [1|S]) :-
subset([], []). % outer L=[]
We can re-write it (nearly) equivalently to push the unifications out of the rules' headers, to make the code's structure more visually apparent:
subset(A,B) :- B=[], A=[].
subset(A,B) :- B=[X | S],
A=[X | L],
subset(L, S).
subset(A,B) :- B=[_ | S],
A= L,
subset(L, S).
So A is a subset of B, if
B=[] and A=[], or
A contains the first element of B, etc. or
A does not contain the first element of B, etc.
That is all.

Count occurrences Prolog

I'm new in Prolog and trying to do some programming with Lists
I want to do this :
?- count_occurrences([a,b,c,a,b,c,d], X).
X = [[d, 1], [c, 2], [b, 2], [a, 2]].
and this is my code I know it's not complete but I'm trying:
count_occurrences([],[]).
count_occurrences([X|Y],A):-
occurrences([X|Y],X,N).
occurrences([],_,0).
occurrences([X|Y],X,N):- occurrences(Y,X,W), N is W + 1.
occurrences([X|Y],Z,N):- occurrences(Y,Z,N), X\=Z.
My code is wrong so i need some hits or help plz..
Here's my solution using bagof/3 and findall/3:
count_occurrences(List, Occ):-
findall([X,L], (bagof(true,member(X,List),Xs), length(Xs,L)), Occ).
An example
?- count_occurrences([a,b,c,b,e,d,a,b,a], Occ).
Occ = [[a, 3], [b, 3], [c, 1], [d, 1], [e, 1]].
How it works
bagof(true,member(X,List),Xs) is satisfied for each distinct element of the list X with Xs being a list with its length equal to the number of occurrences of X in List:
?- bagof(true,member(X,[a,b,c,b,e,d,a,b,a]),Xs).
X = a,
Xs = [true, true, true] ;
X = b,
Xs = [true, true, true] ;
X = c,
Xs = [true] ;
X = d,
Xs = [true] ;
X = e,
Xs = [true].
The outer findall/3 collects element X and the length of the associated list Xs in a list that represents the solution.
Edit I: the original answer was improved thanks to suggestions from CapelliC and Boris.
Edit II: setof/3 can be used instead of findall/3 if there are free variables in the given list. The problem with setof/3 is that for an empty list it will fail, hence a special clause must be introduced.
count_occurrences([],[]).
count_occurrences(List, Occ):-
setof([X,L], Xs^(bagof(a,member(X,List),Xs), length(Xs,L)), Occ).
Note that so far all proposals have difficulties with lists that contain also variables. Think of the case:
?- count_occurrences([a,X], D).
There should be two different answers.
X = a, D = [a-2]
; dif(X, a), D = [a-1,X-1].
The first answer means: the list [a,a] contains a twice, and thus D = [a-2]. The second answer covers all terms X that are different to a, for those, we have one occurrence of a and one occurrence of that other term. Note that this second answer includes an infinity of possible solutions including X = b or X = c or whatever else you wish.
And if an implementation is unable to produce these answers, an instantiation error should protect the programmer from further damage. Something along:
count_occurrences(Xs, D) :-
( ground(Xs) -> true ; throw(error(instantiation_error,_)) ),
... .
Ideally, a Prolog predicate is defined as a pure relation, like this one. But often, pure definitions are quite inefficient.
Here is a version that is pure and efficient. Efficient in the sense that it does not leave open any unnecessary choice points. I took #dasblinkenlight's definition as source of inspiration.
Ideally, such definitions use some form of if-then-else. However, the traditional (;)/2 written
( If_0 -> Then_0 ; Else_0 )
is an inherently non-monotonic construct. I will use a monotonic counterpart
if_( If_1, Then_0, Else_0)
instead. The major difference is the condition. The traditional control constructs relies upon the success or failure of If_0 which destroys all purity. If you write ( X = Y -> Then_0 ; Else_0 ) the variables X and Y are unified and at that very point in time the final decision is made whether to go for Then_0 or Else_0. What, if the variables are not sufficiently instantiated? Well, then we have bad luck and get some random result by insisting on Then_0 only.
Contrast this to if_( If_1, Then_0, Else_0). Here, the first argument must be some goal that will describe in its last argument whether Then_0 or Else_0 is the case. And should the goal be undecided, it can opt for both.
count_occurrences(Xs, D) :-
foldl(el_dict, Xs, [], D).
el_dict(K, [], [K-1]).
el_dict(K, [KV0|KVs0], [KV|KVs]) :-
KV0 = K0-V0,
if_( K = K0,
( KV = K-V1, V1 is V0+1, KVs0 = KVs ),
( KV = KV0, el_dict(K, KVs0, KVs ) ) ).
=(X, Y, R) :-
equal_truth(X, Y, R).
This definition requires the following auxiliary definitions:
if_/3, equal_truth/3, foldl/4.
If you use SWI-Prolog, you can do :
:- use_module(library(lambda)).
count_occurrences(L, R) :-
foldl(\X^Y^Z^(member([X,N], Y)
-> N1 is N+1,
select([X,N], Y, [X,N1], Z)
; Z = [[X,1] | Y]),
L, [], R).
One thing that should make solving the problem easier would be to design a helper predicate to increment the count.
Imagine a predicate that takes a list of pairs [SomeAtom,Count] and an atom whose count needs to be incremented, and produces a list that has the incremented count, or [SomeAtom,1] for the first occurrence of the atom. This predicate is easy to design:
increment([], E, [[E,1]]).
increment([[H,C]|T], H, [[H,CplusOne]|T]) :-
CplusOne is C + 1.
increment([[H,C]|T], E, [[H,C]|R]) :-
H \= E,
increment(T, E, R).
The first clause serves as the base case, when we add the first occurrence. The second clause serves as another base case when the head element matches the desired element. The last case is the recursive call for the situation when the head element does not match the desired element.
With this predicate in hand, writing count_occ becomes really easy:
count_occ([], []).
count_occ([H|T], R) :-
count_occ(T, Temp),
increment(Temp, H, R).
This is Prolog's run-of-the-mill recursive predicate, with a trivial base clause and a recursive call that processes the tail, and then uses increment to account for the head element of the list.
Demo.
You have gotten answers. Prolog is a language which often offers multiple "correct" ways to approach a problem. It is not clear from your answer if you insist on any sort of order in your answers. So, ignoring order, one way to do it would be:
Sort the list using a stable sort (one that does not drop duplicates)
Apply a run-length encoding on the sorted list
The main virtue of this approach is that it deconstructs your problem to two well-defined (and solved) sub-problems.
The first is easy: msort(List, Sorted)
The second one is a bit more involved, but still straight forward if you want the predicate to only work one way, that is, List --> Encoding. One possibility (quite explicit):
list_to_rle([], []).
list_to_rle([X|Xs], RLE) :-
list_to_rle_1(Xs, [[X, 1]], RLE).
list_to_rle_1([], RLE, RLE).
list_to_rle_1([X|Xs], [[Y, N]|Rest], RLE) :-
( dif(X, Y)
-> list_to_rle_1(Xs, [[X, 1],[Y, N]|Rest], RLE)
; succ(N, N1),
list_to_rle_1(Xs, [[X, N1]|Rest], RLE)
).
So now, from the top level:
?- msort([a,b,c,a,b,c,d], Sorted), list_to_rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [[d, 1], [c, 2], [b, 2], [a, 2]].
On a side note, it is almost always better to prefer "pairs", as in X-N, instead of lists with two elements exactly, as in [X, N]. Furthermore, you should keep the original order of the elements in the list, if you want to be correct. From this answer:
rle([], []).
rle([First|Rest],Encoded):-
rle_1(Rest, First, 1, Encoded).
rle_1([], Last, N, [Last-N]).
rle_1([H|T], Prev, N, Encoded) :-
( dif(H, Prev)
-> Encoded = [Prev-N|Rest],
rle_1(T, H, 1, Rest)
; succ(N, N1),
rle_1(T, H, N1, Encoded)
).
Why is it better?
we got rid of 4 pairs of unnecessary brackets in the code
we got rid of clutter in the reported solution
we got rid of a whole lot of unnecessary nested terms: compare .(a, .(1, [])) to -(a, 1)
we made the intention of the program clearer to the reader (this is the conventional way to represent pairs in Prolog)
From the top level:
?- msort([a,b,c,a,b,c,d], Sorted), rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [a-2, b-2, c-2, d-1].
The presented run-length encoder is very explicit in its definition, which has of course its pros and cons. See this answer for a much more succinct way of doing it.
refining joel76 answer:
count_occurrences(L, R) :-
foldl(\X^Y^Z^(select([X,N], Y, [X,N1], Z)
-> N1 is N+1
; Z = [[X,1] | Y]),
L, [], R).

Prolog separating lists

Hello is there any way to separate a list in Prolog into two other lists, the first includes everything before an element and the second everything after the element. For example
A=[1,2,3,5,7,9,0] and element=5
the two lists should be
A1=[1,2,3] and A2=[7,9,0]
I don't care about finding the element just what to do next
it's easy as
?- Elem = 5, A = [1,2,3,5,7,9,0], append(A1, [Elem|A2], A).
edit to explain a bit...
append/3 it's a relation among 3 lists.
It's general enough to solve any concatenation on proper lists - when not there are circular arguments.
The comparison it's a plain unification, that take place on second argument. That must be a list beginning with Elem. Prolog list constructor syntax is [Head|Tail]. To make unification succeed, Elem must match the Head.
Here's an alternative method, illustrating how to handle it with list recursion:
split([E|T], E, [], T).
split([X|T], E, [X|LL], LR) :-
X \== E,
split(T, E, LL, LR).
Or better, if your Prolog supports dif/2:
split([E|T], E, [], T).
split([X|T], E, [X|LL], LR) :-
dif(X, E),
split(T, E, LL, LR).
Examples:
| ?- split([1,2,3,4,5], 3, L, R).
L = [1,2]
R = [4,5] ? ;
no
| ?- split([1,2,3,4,5], 5, L, R).
L = [1,2,3,4]
R = [] ? ;
(1 ms) no
| ?- split([1,2,3,4,5], 1, L, R).
L = []
R = [2,3,4,5] ? ;
no
| ?-
It is a sort of specialized twist on append/3 as CapelliC showed.

Prolog programs - how to make it work?

I have these two programs and they're not working as they should. The first without_doubles_2(Xs, Ys)is supposed to show that it is true if Ys is the list of the elements appearing in Xs without duplication. The elements in Ys are in the reversed order of Xs with the first duplicate values being kept. Such as, without_doubles_2([1,2,3,4,5,6,4,4],X) prints X=[6,5,4,3,2,1] yet, it prints false.
without_doubles_2([],[]).
without_doubles_2([H|T],[H|Y]):- member(H,T),!,
delete(H,T,T1),
without_doubles_2(T1,Y).
without_doubles_2([H|T],[H|Y]):- without_doubles_2(T,Y).
reverse([],[]).
reverse([H|T],Y):- reverse(T,T1), addtoend(H,T1,Y).
addtoend(H,[],[H]).
addtoend(X,[H|T],[H|T1]):-addtoend(X,T,T1).
without_doubles_21(X,Z):- without_doubles_2(X,Y),
reverse(Y,Z).
The second one is how do I make this program use a string? It's supposed to delete the vowels from a string and print only the consonants.
deleteV([H|T],R):-member(H,[a,e,i,o,u]),deleteV(T,R),!.
deleteV([H|T],[H|R]):-deleteV(T,R),!.
deleteV([],[]).
Your call to delete always fails because you have the order of arguments wrong:
delete(+List1, #Elem, -List2)
So instead of
delete(H, T, T1)
You want
delete(T, H, T1)
Finding an error like this is simple using the trace functionality of the swi-prolog interpreter - just enter trace. to begin trace mode, enter the predicate, and see what the interpreter is doing. In this case you would have seen that the fail comes from the delete statement. The documentation related to tracing can be found here.
Also note that you can rewrite the predicate omitting the member check and thus the third clause, because delete([1,2,3],9001,[1,2,3]) evaluates to true - if the element is not in the list the result is the same as the input. So your predicate could look like this (name shortened due to lazyness):
nodubs([], []).
nodubs([H|T], [H|Y]) :- delete(T, H, T1), nodubs(T1, Y).
For your second question, you can turn a string into a list of characters (represented as ascii codes) using the string_to_list predicate.
As for the predicate deleting vovels from the string, I would implement it like this (there's probably better solutions for this problem or some built-ins you could use but my prolog is somewhat rusty):
%deleteall(+L, +Elems, -R)
%a helper predicate for deleting all items in Elems from L
deleteall(L, [], L).
deleteall(L, [H|T], R) :- delete(L, H, L1), deleteall(L1, T, R).
deleteV(S, R) :-
string_to_list(S, L), %create list L from input string
string_to_list("aeiou", A), %create a list of all vovels
deleteall(L, A, RL), %use deleteall to delete all vovels from L
string_to_list(R, RL). %turn the result back into a string
deleteV/2 could make use of library(lists):
?- subtract("carlo","aeiou",L), format('~s',[L]).
crl
L = [99, 114, 108].
while to remove duplicates we could take advantage from sort/2 and select/3:
nodup(L, N) :-
sort(L, S),
nodup(L, S, N).
nodup([], _S, []).
nodup([X|Xs], S, N) :-
( select(X, S, R) -> N = [X|Ys] ; N = Ys, R = S ),
nodup(Xs, R, Ys).
test:
?- nodup([1,2,3,4,4,4,5,2,7],L).
L = [1, 2, 3, 4, 5, 7].
edit much better, from ssBarBee
?- setof(X,member(X,[1,2,2,5,3,2]),L).
L = [1, 2, 3, 5].

return all levels of a binarytree in prolog

I'm trying to get a program to return the levels of a BT in the way of a list and I'm stuck at this:
nivel(nodo(L,Root,R)) :- nivel(nodo(L,Root,R),X),writeln(X).
nivel(vacio,[]).
nivel(nodo(L,Root,R),[Root|T]) :- nivel(L,T),nivel(R,T),writeln(T).
An example input-output of what I'm trying is:
nivel(nodo(nodo(vacio,4,vacio), t, nodo(vacio,r,vacio))
X =[t]
X =[4,r]
problem is I don't know how to make the program get the new Roots.
Any ideas? Also, thanks in advance!
Here goes a solution, it traverses the tree once an builds a list of the items in each level.
nivel(Arbol, SubNivel):-
nivel(Arbol, [], [], Items),
member(SubNivel, Items),
SubNivel \= [].
nivel(vacio, Items, SubNiveles, [Items|SubNiveles]).
nivel(nodo(Izq, Item, Der), Items, [], [[Item|Items]|NSubNiveles]):-
nivel(Izq, [], [], [MSubItems|MSubNiveles]),
nivel(Der, MSubItems, MSubNiveles, NSubNiveles).
nivel(nodo(Izq, Item, Der), Items, [SubItems|SubNiveles], [[Item|Items]|NSubNiveles]):-
nivel(Izq, SubItems, SubNiveles, [MSubItems|MSubNiveles]),
nivel(Der, MSubItems, MSubNiveles, NSubNiveles).
The second clause of nivel/4 is a hack due to the fact that the algorithm does not know in advance the height of the tree.
Test case:
?- nivel(nodo(nodo(nodo(nodo(vacio,f,vacio),e,nodo(vacio,g,vacio)),b,vacio),a,nodo(vacio,c,nodo(vacio,d,vacio))), X).
X = [a] ; --> Root
X = [c, b] ; --> First Level
X = [d, e] ; --> Second Level
X = [g, f] ; --> Third Level
Quite a tricky one for Prolog, but here's one solution to consider which provides a true level-order (L-R breadth-first) tree traversal:
nivel(nodo(L,Root,R), Level) :-
depth_value_pairs(nodo(L,Root,R), 0, DVPairs),
keylistmerge(DVPairs, Groups),
maplist(keyvalue, Groups, _, Values),
member(Level, Values).
nivel/2 is your entry predicate. Basically, it uses depth_value_pairs/3, which generates solutions of the form Depth-Value (e.g., 0-t to represent the root node t at ply depth 0, or 1-4 to represent the node 4 at ply depth 1, etc.). Then, it uses keylistmerge/2 to merge the list all depth-value pairs into depth groups, e.g., [0-[t], 1-[4,t], ...]. Then, the maplist(keyvalue... call busts the Depth- parts from the lists, and the final predicate call member/2 selects each list to bind to the output Level.
Here are the other predicate definitions:
depth_value_pairs(vacio, _, []).
depth_value_pairs(nodo(L, Root, R), Depth, [Depth-Root|Level]) :-
NextLevel is Depth + 1,
depth_value_pairs(L, NextLevel, LL),
depth_value_pairs(R, NextLevel, RL),
append(LL, RL, Level).
keyvalue(K-V, K, V).
keylistmerge(KVL, MKVL) :-
keysort(KVL, [K-V|KVs]),
keylistmerge([K-V|KVs], K, [], MKVL).
keylistmerge([], K, Acc, [K-Acc]).
keylistmerge([K0-V|KVs], K, Acc, MKVL) :-
K == K0, !,
append(Acc, [V], NewAcc),
keylistmerge(KVs, K, NewAcc, MKVL).
keylistmerge([K0-V|KVs], K, Acc, [K-Acc|MKVs]) :-
keylistmerge(KVs, K0, [V], MKVs).
Exercising this gives us:
?- nivel(nodo(nodo(vacio,4,nodo(vacio,5,vacio)), t, nodo(vacio,r,vacio)), Level).
Level = [t] ;
Level = [4, r] ;
Level = [5] ;
false.
Note that we rely on the built-in keysort/2 to be order-preserving (stable) so as to preserve the L-R order of nodes in the binary tree.

Resources