List is the list of values in leaf nodes of a binary tree and I am trying to figure out how to output just that. This is giving me all the nodes but I need just the leaves.
lea(nil,[]).
lea(t(X,L,R),[X|L]) :-
lea(L,L1),
lea(R,L2),
append(L1,L2,L).
Running this gives me:
?- lea(t(a,t(b,t(d,nil,nil),t(e,nil,nil)),t(c,nil,t(f,t(g,nil,nil),nil))),
List).
List = [a, b, d, e, c, f, g]
but I need
List = [d, e,g]
Is it possible.
Let's use a DCG - a Definite Clause Grammar. We start with your original definition:
lea(T, L) :-
phrase(values(T), L).
values(nil) -->
[].
values(t(X,L,R)) -->
[X],
values(L),
values(R).
Now, we need to restrict ourselves to those t/3
that are leaves. One possibility is to enumerate all cases:
lea2(T, L) :-
phrase(leaves(T), L).
leaves(nil) -->
[].
leaves(t(X,nil,nil)) -->
[X].
leaves(t(_,L,R)) -->
{ dif(L+R,nil+nil) },
leaves(L),
leaves(R).
It would be even better and more efficient to use a conditional construct similar to if_/3
. I want to leave this to someone interested.
First, we extend if_/3
to work with DCG's:
if_(C_1, Then_0, Else_0) --> % if_//3
{ call(C_1, Truth) },
{ functor(Truth, _, 0) }, % safety check
( { Truth == true } -> phrase(Then_0)
; { Truth == false }, phrase(Else_0)
).
Using if_//3
and (=)/3
we can handle non-nil tree nodes with one clause (instead of two):
lea3(T, Ls) :-
phrase(leaves(T), Ls).
leaves(nil) --> [].
leaves(t(X,L,R)) -->
if_(L-R = nil-nil, [X], []),
leaves(L),
leaves(R).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With