I want to write a program in Prolog that builds a list of all the even integers that reside in a b-tree.
This is what I've written so far. A predicate that counts all the elements in the tree. I don't know where to scratch.
Domains
element=integer
tree=a(tree,element,tree);void
list=integer*
Predicates
nondeterm count(tree,element)
nondeterm count_even(tree,list)
Clauses
count(a(void,Number,void),1).
count(a(Esq,_,Dreta),Counter) :-
count(Esq,Counter1),
count(Dreta,Counter2),
Counter=Counter1+Counter2+1.
Goal
count(a(a(void,1,void),5,a(a(void,4,void),1,a(void,4,void))),N).
Thanks a lot.
Dunno anything about Visual Prolog, but in normal Prolog, I'd do something like the following...
First, I'd denote an empty btree as the atom btree and represent a non-empty btree as a structure of arity 3, thus:
btree( Payload, LeftChildren, RightChildren )
where Payload is the data for the node (an integer apparently), with LeftChildren and RightChildren being the btrees representing, respectively, the left and right children of the current node.
Traversing the tree to count those nodes with even-valued nodes is simple. The public predicate has arity 2, accepting the [bound] btree structure to be examined, and a bound or unbound value representing the count of even items. It calls an internal, recursive "helper" predicate that walks a tree and develops the count.
count_even( T , N ) :- count_even( T , 0 , N ) .
The internal predicate is simple as well. Having arity 3, the first argument is the tree to be examined, the second is an accumulator and the third is the final count (which won't be unified until the very end). There are two possible cases.
If the tree is empty, we have the final count:
count_even( btree , N , N ) .
If the tree is non-empty, we examine the current node, then recursively walk the left and right child trees, thusly:
count_even( btree( V , L , R ) , T , N ) :-
is_even( V , X ) ,
T1 is T+X ,
count_even( L , T1 , T2 ) ,
count_even( R , T2 , N )
.
We also need a trivial helper to tell us whether a particular value is even or odd:
is_even( V , 1 ) :- 0 is V mod 2 , ! .
is_even( V , 0 ) .
It should be noted that the data structure you're using is not a b-tree, per se: it is a binary tree.
B-trees are something of a generalization of a height-balanced binary tree optimized for disk storage. Each node has a variable number of keys and a variable number of children (corresponding to the number of keys). For more information, see
http://en.wikipedia.org/wiki/B-tree
http://cis.stvincent.edu/html/tutorials/swd/btree/btree.html
http://www.dtic.upf.edu/~rramirez/TA/btrees.pdf
Here's a picture of a B-tree:
And a picture of a binary tree:
You have to check every node to see if it's even or odd and only count the ones that are even.
A simple modification to your program should do (however I'd do it a bit different):
element=integer
tree=a(tree,element,tree);void
list=integer*
Predicates
nondeterm count_even(tree,list)
Clauses
count_even(a(void,Number,void),Value):-
Value = 1 - Number mod 2.
count_even(a(Esq,Number,Dreta),Counter) :-
count_even(Esq,Counter1),
count_even(Dreta,Counter2),
count_even=Counter1 + Counter2 + 1 - Number mod 2.
I just count 1 - Number mod 2 which is 1 when the number is even and 0 otherwise.
Related
I am a noob prolog programmer and facing a difficulty with one of the basic problems that have been given in the book where I am learning from. The question. The question basically asks us to write down a Prolog procedure that takes two lists as arguments, and succeeds if the first list is twice the size of the second list and the two lists start with the same element. The procedure should return false if the two lists are empty.
For example it should return true if we pass the query:
a2b([a,a,a,a],[a,b]).
and would fail with a query like:
a2b([a,a],[a,b,b,b]).
I don't know how to solve this problem recursively, any help would be appreciated. Thanks!
First, the request about lengths:
/* empty list fulfills request */
a2b_length([],[]).
/* non-empty: discard two elements of first list,
one of second list, and verify
remainder */
a2b_length([_,_|Q1],[_|Q2]) :-
a2b_length(Q1,Q2).
Now, we can add the requirement "starts by the same term and are non empty", and write the last clause:
a2b([X,_|Q1],[X|Q2]) :-
a2b_length(Q1,Q2).
Cute problem. It can be solved using the following code:
% fail of the first element of each list don't unify
% or if one or both lists are empty
a2b([First| List1], [First| List2]) :-
% calculate the length of the second list
% while traversing both lists in parallel
a2b_first(List2, 1, N, List1, Rest1),
% check that the length of the rest of the first
% list is equal to the length of the second list
a2b_second(Rest1, N).
a2b_first([], N, N, Tail1, Tail1).
a2b_first([_| Tail2], N0, N, [_| Tail1], Rest1) :-
N1 is N0 + 1,
a2b_first(Tail2, N1, N, Tail1, Rest1).
a2b_second([], 0).
a2b_second([_| Tail1], N) :-
M is N - 1,
a2b_second(Tail1, M).
Of course, there's a simpler (but not as fun to code!) solution:
% fail of the first element of each list don't unify
% or if one or both lists are empty
a2b([First| List1], [First| List2]) :-
length([First| List1], N1),
length([First| List2], N2),
N1 is 2 * N2.
The length/2 predicate is usually available either as a built-in predicate or as a library predicate.
For learning Prolog, studying the first solution is interesting. For example, it exemplifies how to take advantage of first-argument indexing and how to use accumulators for writing predicates that are tail-recursive (and thus space efficient).
Also, the first solution can be more efficient than the second solution. In the second solution, we always traverse both lists to the end to find their lengths. But, in the first solution, that is not always necessary.
Don't overthink things: just describe the solution and let Prolog sort it out.
The solution doesn't require counting or predicates other than its trivial self. It's all pattern matching. We have a special (terminating case), asserting that a list of length 2 is twice as long as a list of length 1 (which should be pretty obvious):
is_twice_as_long_as( [_,_] , [_] ) .
Then there is the general case, which asserts that given two lists of arbitrary length, the left is twice as long as the right IF we can (A) remove 2 items from the left, (B) remove 1 item from right, and recursively assert that their respective remainders are likewise twice as long:
is_twice_as_long_as( [_,_|A] , [_|B] ) :- is_twice_as_long_as( A , B ) .
Giving us the finished product:
is_twice_as_long_as( [_,_] , [_] ) .
is_twice_as_long_as( [_,_|A] , [_|B] ) :- is_twice_as_long_as( A , B ) .
Easy!
Edited to note the requirement that the two lists begin with the same element:
Depending on how that is interpreted...
this requires that the lists have a common head on each iteration:
is_twice_as_long_as( [A,_] , [A] ) .
is_twice_as_long_as( [A,_|L] , [A|R] ) :- is_twice_as_long_as( L , R ) .
this does the check for a common head just once::
is_twice_as_long_as( [A|As] , [A|Bs] ) :-
is_2x([A|As],[A|Bs]) .
is_2x( [_,_] , [_] ) .
is_2x( [_,_|L] , [_|R] ) :- is_2x( L , R ) .
I have to write a predicate ListInTree(T,X) which is true when T is a tree with a list in each node, and X is the concatenation of all the lists (assuming to visit in Pre-order).
I really can't understand how to use the recursion to visit all the tree.
Thanks
You do not indicate what tree you are after, so I have to guess. The best in this case is to use a DCG, for grammars are built to model concatenation in the most natural manner possible:
seq([]) -->
[].
seq([E|Es]) -->
[E],
seq(Es).
flattened(empty) -->
[].
flattened(node(Xs, L, R)) -->
seq(Xs),
flattened(L),
flattened(R).
tree_flattened(T, Es) :-
phrase(flattened(T), Es).
For the sake of example, let us assume the following representation for a tree:
The atom nil represents the empty tree.
The structure tree/3 represents a non-empty tree tree( Left , Right , Payload ) where Left and Right represent (respectively and recursively) the left and right subtrees, and Payload is the payload for the node: in your case, a list.
Many/Most recursive problems have 1 or 2 "special cases" and the more general case. This is no different:
The special case is that of the empty tree: flattening it produces the empty list.
The general case is that of a non-empty tree: flatting it consists of the following steps:
Flatten the left subtree to produce a list
Flatten the right subtree to product a list
The result is that obtained by the concatenation of
the flattened left subtree
the current node's payload
the flattened right subtree
The Prolog code to accomplish this is pretty much identical to the English description above:
flatten_tree( nil , [] ) . % flattening the empty tree yields an empty list, n'est-ce-pas?
flatten_tree( tree(Left,Right,Payload) , Result ) :- % flattening a non-empty tree consists of
flatten_tree( Left , Prefix ) , % - flattening the left subtree,
flatten_tree( Right , Suffix ) , % - flattening the right subtree,
concatenate( Prefix , Payload , Suffix , Result ) % - concatenating the three parts
. % - easy!
concat( Xs, Ys , Zs , Rs ) :-
append(Xs,Ys,T1) ,
append(T1,Zs,Rs)
.
One might note that another approach might be to use findall/3 and append/2 (if you're using SWI prolog).
First you need a predicate to visit the tree via backtracking:
visit( tree(L,_,_) , P ) :- visit( L , P ) . % visit the left subtree
visit( tree(_,_,P) , P ) . % visit the current node
visit( tree(_,R,_) , P ) :- visit( R , P ) . % visit the right subtree
Feel free to rearrange the order of the clauses to get the ordering you'd like. Once you have that, flattening the tree is trivial:
flatten_tree( Tree , List ) :-
findall( X, visit(Tree,X) , Xs ) ,
append(Xs,List)
.
sumPicker([[]|_], Y, Z).
sumPicker([X|X1], Y, Z):-
downList(Y, X, Sum),
Total is Z,
Z is Total + Sum,
sumPicker(X1,Y, Z).
downList([Z|_], 1, Z).
downList([_|B],Count, Number):- Count > 1,
SendCount is Count - 1,
downList(B, SendCount, Number).
So this code is basically suppose to take in Two lists sumPicker([3,5], [1,2,3,4,5,6], X). The program then takes the first list and depending on the value of the number, so in this case 3, it will find the third number in the second list then it will find the 5th number of the second list and add them together.
ERROR: is/2: Arguments are not sufficiently instantiated is what i am getting
I'm assuming that your instructor would like you to work out the recursion yourself, rather than using built-in list operations. To that end, you could approach it something like this, using no built-ins at all.
A common prolog idiom is to have a simple "public" predicate that invokes a "helper" predicate that carries state (in this case, the current position in the list and the running sum). Often, that "helper" predicate will have the same functor (name) as the public predicate, with a higher arity (number of arguments).
So, first we have the public predicate, sum_of_desired/3:
sum_of_desired( Indices , Numbers , Sum ) :- % to sum certain list elements,
sum_of_desired( Indices , Numbers , 0 , Sum ) - % invoke the helper
. %
All it does is invoke the helper, sum_of_desired/4. This helper predicate carries an extra argument that is its state: an accumulator that contains the running sum. When it succeeds, that running sum is unified with the final total. This is because, in Prolog, you can't change the value of a variable: once you assign a value to a variable, it ceases to be variable. It become that with which it was unified (that's it's called unification). The only way to undo that assignment is via backtracking.
Typically, a recursive problem has a few special cases and a more general case. So, here, our helper predicate has 2 clauses:
The first clause is the special case: the list of desired indices is empty, in which case the finally sum is the current value of the accumulator (0 initially).
the second clause is the recursive general case: here we find the desired list item, add it to the running total and recurse down, moving on to the next item in the list of desired list items.
sum_of_desired( [] , _ , S , S ) . % the list of desired indices is empty: unify the accumulator with the result.
sum_of_desired( [I|Is] , L , T , S ) :- % otherwise...
get_nth_item(I,L,N) , % - get the nth item from the list
T1 is T+N , % - add it to the running total
sum_of_desired(Is,T1,S) % - and recurse down
. %
Finally, this predicate, get_nth_item/3, simple recursively walks the list, looking for the nth item in the list, where n is relative to 1 (e.g., the first item in the list is at index 1). When it finds it, it's returned as the 3rd argument of the predicate.
Again, here you will note that we have a single terminating special case and the more general recursive special case:
get_nth_item( 1 , [X|_] , X ) . % found it!
get_nth_item( N , [_|Xs] , R ) :- % otherwise...
N > 1 , % - if N > 1 ,
N1 is N-1 , % - decrement N
nth_item( N1 , Xs , R ) % - recurse down.
. % - easy!
So, the story began with counting the number of elements inside a list.
Then, I encountered this code when I searched for the solutions in Internet.
count([],0).
count([_HEAD|TAIL],X) :-
count(TAIL,X1),
X is X1+1.
However, there was no clear explanation on how the code actually worked and that is why I ask here in order to get a clear explanation about this code.
Hope that someone can explain step by step so that I can understand better.
Please think declaratively. You are relating a list to its length, so a better, relational name would be list_length/2: The first argument is a list, the second its length.
Obviously, the length of the empty list [] is 0.
Further, if Tail is a list of length L0, then the length of [_|Tail] is the number L0 + 1.
count([] ,0) means that an empty list has 0 element.
Now, to count the elements of a list
count([_HEAD|TAIL],X):-
% we remove the first element of the list
% we count the elements of the rest of the list
count(TAIL,X1),
% and we add 1 to the number of the elements of the rest
X is X1+1.
Learning to think recursively is hard. Most recursive problems can be broken down into a few "special cases" and the general case. In this case, we have two cases:
the empty list. This is our special case. The length of the empty list is ALWAYS zero.
A non-empty list. This is our general case.We have the list's head (a single item) and its tail (the remainder of the list: zero or more items). So, we can say that the length of a non-empty list is the length of its tail, plus 1 (the head).
Prolog lets you simply declare these to be facts defining truth. Then we let the Prolog inference engine determine the truth or falsity of an assertion. To whit:
count( [] , 0 ) . % The count of an empty list is zero
count( [_|Xs] , N ) :- % If the list is non-empty,
count( Xs, T ) , % - we count its tail as T
N is T+1 % - and then add 1.
. %
Then... you can say things like:
?- count([],3).
false.
?- count([a,b,c],3).
true.
This also works in a generative manner:
?- count( List , 3 ) .
List = [_G938, _G941, _G944] .
Or even...
?- count(X,N).
X = [], N = 0 ;
X = [_G950], N = 1 ;
X = [_G950, _G953], N = 2 ;
X = [_G950, _G953, _G956], N = 3 ;
...
Note that this is not tail-recursive and feed a list of sufficient length, will eventually overflow its stack.
You can write it in a tail-recursive manner as well, which might be easier to understand:
count( Xs , N ) :- % to count the number of items in a list,
count( Xs , 0 , N ) % - invoke the helper, seeding the accumulator with 0.
. %
count( [] , N , N ) . % if the source list is empty, the accumulator contains the number of items in the list.
count( [_|Xs] , T , N ) :- % otherwise (source list is non-empty)
T1 is T+1 , % - increment the accumulator, and
count(Xs,T1,N) % - recurse down on the tail, passing the incremented accumulator
. %
I want to implement a predicate (vecLine2BitLine) which does the following:
get two lists and a number the first list is the length of blocks (the elements of the blocks are '$') and the second list contains the indexes that these blocks should be placed at meaning:
vecLine2BitLine([1,2,1],[2,5,9],12,BitLine).
BitLine=[' ','$',' ',' ','$','$',' ',' ','$',' ',' ',' '].
explanation:a block of length 1 is at index 2
and a block of length 2 is at index 5 and so on..
insert_at_mul : inserts an element N times (it works perfectly,dupli and my_flatten were implemented previously so i used them)
Ive been trying to activate insert_at_mul N times when N is the length of the list X and Y
in the predicate vecLine2BitLine.
dupli(L1,N,L2) :- dupli(L1,N,L2,N).
dupli([],_,[],_).
dupli([_|Xs],N,Ys,0) :- dupli(Xs,N,Ys,N).
dupli([X|Xs],N,[X|Ys],K) :- K > 0, K1 is K - 1, dupli([X|Xs],N,Ys,K1).
my_flatten(X,[X]) :- \+ is_list(X).
my_flatten([],[]).
my_flatten([X|Xs],Zs) :- my_flatten(X,Y), my_flatten(Xs,Ys), append(Y,Ys,Zs).
insert_at_mul(L,X,K,R,N):-dupli([X],N,XX) , insert_at(L,XX,K,L1) , my_flatten(L1,R).
get_num_spaces(L,N,X):-sum(L,S), X is N-S.
generate_spaces(N,L,X):- insert_at_mul(L,'',1,X,N).
vecLine2BitLineAux([],[],_,_,_).
vecLine2BitLineAux([X|Tail1],[Y|Tail2],N,L,Lnew):- insert_at_mul(L,'*',Y,Lnew,X) ,vecLine2BitLineAux(Tail1,Tail2,N,Lnew,R). // problem here!!!
vecLine2BitLine(X,Y,N,L):- get_num_spaces(X,N,Z) , generate_spaces(Z,[],ZZ) , vecLine2BitLineAux(X,Y,N,ZZ,L).
now the problem is that in the function vecLine2BitLine i cant activate insert_at_mul N times(thats what i tried to do in this code, but failed).
how can I fix vecLine2BitLine for it to work properly as in returning the correct output by actually activating the predicate insert_at_mul N times??
THANKS!
added :
vecLine2BitLine : input parameters : (L1,L2,N,Result)
N: after activating the predicate Result will be N in length.
L1: L1 is a list of numbers each number indicates the length of a block, a block is comprised of a Sequence of '$'.
L2: L2 is a list of numbers the numbers are indices for where the blocks in L1 should be placed.
example:
vecLine2BitLine([3,2],[1,5],9,BitLine).
we can look at the input better as tuples :
vecLine2BitLine[(3,1),(2,5)],9,BitLine).
(3,1) : there is a sequence of '' 3 times at index 1
(2,5) : there is a sequence of '' 2 times at index 5
in our example 9 is the length of BitLine at the end and we have to insert into the
list BitLine 3+2 of the "special chars" '*' but we have 9-(3+2) places left in the list
so we add '' in those places and then we get:
BitLine=['$','$','$','','$','$','','','',''].
This is kind of a nice problem because you can use the arguments as loop counters. The K argument gets you to the proper index. Let's just traverse the list and find a particular index as an example. Notice the base case is that you're at the right element, and the inductive case is prior to the right element.
traverse(1, [X|_], X).
traverse(N, [_|Xs], X) :- N > 0, N0 is N-1, traverse(N0, Xs, X).
We're going to apply that pattern to insert_at/4 to get to the right location in the list. Now let's write a repeat/3 predicate that repeats X N times in a new list L. This time the base case is when we've added all the repetitions we care to, and the inductive case is that we'll add another instance.
repeat(1, X, [X]).
repeat(N, X, [X|Xs]) :- N > 0, N0 is N-1, repeat(N0, X, Xs).
You can see the similarity of structure between these two. Try to combine them into a single predicate. Since this is homework, I'll stop here. You're inches from the goal.