/* ************************************************************* */
/* The following predicate checks whether a "mobile" is balanced */

balance(leaf(N), N).
balance(node(L,R), W) :- balance(L, N), balance(R, N), W is 2 * N.

/* ************************************************************* */
/* The following are some examples of mobiles                    */

example(1, node(node(leaf(2), leaf(2)), node(leaf(2), leaf(2)))).
example(2, node(node(leaf(2), node(leaf(1), leaf(1))), 
                node(leaf(2),leaf(2)))).
example(3, node(node(node(leaf(2), leaf(2)),
                     node(leaf(2), node(leaf(1), leaf(1)))),
                node(leaf(4), leaf(4)))).
example(4, node(node(node(leaf(2), leaf(2)),
                     node(leaf(1), node(leaf(1), leaf(1)))),
                node(leaf(4), leaf(4)))).

/* ************************************************************* */
/* The following predicate implements the Fibonacci function     */

fib(0,0).
fib(1,1).
fib(N,F) :- N > 1, N1 is N - 1, N2 is N - 2,
            fib(N1,F1), fib(N2, F2), F is F1 + F2.

/* ************************************************************* */
/* The following predicate generates all natural numbers         */

nats(0).
nats(N) :- nats(M), N is M + 1.

/* ************************************************************* */
/* example of queries: 

   ?- nats(N),fib(N,F).  Generates all Fibonacci numbers
   
   ?-  nats(N),fib(N,F), F is N*N. Generates all Fibonacci 
   numbers that are equal to the quare of their index            */
 
/* ************************************************************* */
/* The following predicate generates the frontier of a tree      */

frontier(leaf(N),[N]).

frontier(node(L,R), F) :- 
  frontier(L,F1), frontier(R,F2), append(F1,F2,F).


/* ************************************************************* */
/* The following predicate generates the frontier of a tree      */
/* using difference lists                                        */

front(leaf(N),[N|L]-L).
front(node(L,R), A-C) :- front(L,A-B), front(R,B-C).

/* ************************************************************* */
/* The following predicate defines concatenation (append) with   */
/* difference lists                                              */

ccat(A - B, B - C, A - C).

/* ************************************************************* */
