Hello I have to solve some prolog problems with lists but i can't figure it out how these work.
I have to add "1" after every even element in a list, and to make the difference of 2 lists.
I know this seems easy, in other language like java or c# i would make it very easy, but prolog it's giving me headaches.
Please help me :|
Edited to note the clarified problem statement ("even item" meaning the item's value is even (rather than the item's ordinal position within the list):
insert_one_after_even_items( [] , [] ). % if the source list is exhaused, we're done.
insert_one_after_even_items( [X|Xs] , [X,1|Ys] ) :- % otherwise,
0 is X mod 2 , % - if the number is even, prepend it and a 1 to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. %
insert_one_after_even_items( [X|Xs] , [X|Ys] ) :- % otherwise,
1 is X mod 2 , % - if the number is odd, prepend it to the result list, and
insert_one_after_even_items( Xs , Ys ) % - recurse down.
. % Easy!
For your second problem, producing the difference between two lists, are you talking about set differences? If so, given two sets A and B, are you talking about the relative difference (all elements of A that do not exist in B), or the absolute difference (all elements of either A or B that do not exist in both sets)?
To solve the relative set difference problem (Find all members of A that do not also exist in B), you can use the built-in member/2 predicate:
relative_difference( [] , _ , [] ) . % if the source list is exhausted, we're done
relative_difference( [A|As] , Bs , R ) :- % if the source list is non-empty, and
member(A,Bs) , % - the current A is an element of B,
! , % - we insert a deterministic cut (no backtracking)
relative_difference( As , Bs , R ) % - and recurse down, discarding the current A
. %
relative_difference( [A|As] , Bs , [A|R] ) :- % if the source list is non-empty (and A is not an element of B due to the cut inserted earlier)
relative_difference( As , Bs , R ) % we simply add A to the result list and recurse down.
.
One thing you will note here: we are building the result list in all of these examples is built from a variable. The tail of the list is unbound (and passed as the new result to the next recursive call, where it either become a new list node or, at the very end, the empty list.
This has the effect of
building the list in order (rather than in reverse order).
if the result was bound on the initial call, unification against the expected result occurs item by item as the recursion proceeds, which means
execution is short-circuited when the first unification failure occurs.
If your prolog implementation doesn't have member/2 as a built in, it's easy enough to implement. Something like this ought to do it:
member(X,[X|T]) :- ! . % A hit! cut and succeed.
member(X,[_|T]) :- member(X,T) . % ... and a miss. Just recurse down on the tail.
Related
%reverse_List
reverseList(H|T,ReversedList):-
reverseListHelper(T,[H],ReversedList).
reverseListHelper([],Accumulator.Accumulator).
reverseListHelper([H|T],Accumulator,ReversedList):-
reverseListHelper(T,[H|Accumulator],ReversedList).
I am beginner to prolog, what wrong with this code ?
it's just giving the output false
kindly explain thanks
I understand the theory of how recursive works in list reversing but not the code much, if any one could explain line by line would be great thanks
One can look at a list in Prolog as essentially a FIFO (first-in/first-out) stack: you can examine, add or remove things only from the top/head: the remainder of the list is opaque.
Reversal of such a list, then, consists of repeatedly (and recursively) popping items from the source stack and pushing each such popped item onto a result stack.
And a common idiom in prolog is the use of a helper predicate with the same name, but different arity, where the additional argument(s) carry whatever extra state is required to solve the problem. In this case, the extra state needs is a list onto which we can push/prepend things as we go, thus building the result in reverse order.
That leads to an implementation of reverse_list/2 that looks like this:
reverse_list( Xs, Ys ) :- reverse_list( Xs , [] , Ys ) .
The helper that does all the work isn't much more complicated. There are just two cases:
The limiting case, where the source list is the empty list, and
The general case, where the source list is non-empty
The limiting case is easy: if the source list is exhausted, the accumulator, whatever it might contain, is the reversed list. That gives us
reverse_list( [] , Zs, Zs ) .
The general case merely involves
removing the head of the source list,
prepending it to the accumulator, and
recursing down on the tails.
Which leads to this (you might note that we leave the final result alone until we hit the limiting case here)
reverse( [X|Xs] , [X|Ys] , Zs ) :- reverse(Xs,Ys,Zs)
Putting it all together, we get
% reverse/2 ----------------------------------------------------------
%
% reverse( Source, Reverse )
%
% Simply invoke the helper predicate, seeding the accumulator with the
% empty list.
%
% --------------------------------------------------------------------
reverse( Xs , Ys ) :- reverse(Xs,[],Ys) .
% reverse/3 ----------------------------------------------------------
%
% reverse( Source, Accumulator, Reversed )
%
% --------------------------------------------------------------------
reverse( [] , Zs , Zs ) . % source list empty: unify accumulator and result
reverse( [X|Xs] , [X|Ys] , Zs ) :- % non-empty source? Put X on the accumulator, and
reverse(Xs,Ys,Zs) . % - recurse down on the tails.
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 ) .
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 have to write a deep version of a predicate that adds a number to each number element in a list and I've done the non-deep version:
addnum(N,T,Y)
this gives something like:
e.g. ?-addnum(7,[n,3,1,g,2],X).
X=[n,10,8,g,9]
but I want to create a deep version of addnum now which should do this:
e.g. ?-addnumdeep(7,[n,[[3]],q,4,c(5),66],C).
X=[n,[[10]],q,11,c(5),73]
Can someone give me some advice? I have started with this:
islist([]).
islist([A|B]) :- islist(B).
addnumdeep(C,[],[]).
addnumdeep(C,[Y|Z],[G|M]):-islist(Z),addnum(C,Y,[G,M]),addnumdeep(C,Z,M).
but I don't think my logic is right. I was thinking along the lines of checking if the tail is a list then runing addnum on the head and then runnig addnumdeep on the rest of the tail which is a list?
maybe you could 'catch' the list in first place, adding as first clause
addnum(N,[T|Ts],[Y|Ys]) :- addnum(N,T,Y),addnum(N,Ts,Ys).
This is one solution. The cut is necessary, or else it would backtrack and give false solutions later on. I had tried to use the old addnum predicate, but you can't know if you have to go deeper afterwards, so it would only be feasible if you have a addnum_3levels_deep predicate and even then it would be clearer to use this solution and count the depth.
addnumdeep(N,[X|Y],[G|H]):-
!, % cut if it is a nonempty list
(number(X)->
G is N + X;
addnumdeep(N,X,G)), % recurse into head
addnumdeep(N,Y,H). % recurse into tail
addnumdeep(_,A,A).
Note that this also allows addnumdeep(7,3,3). if you want it to be addnumdeep(7.3.10), you'll have to extract the condition in the brackets:
addnumdeep(N,[X|Y],[G|H]):-
!, % cut if it is a nonempty list
addnumdeep(N,X,G),
addnumdeep(N,Y,H).
addnumdeep(N,X,Y):-
number(X),!, % cut if it is a number.
Y is N+X.
addnumdeep(_,A,A).
This solution is nicer, because it highlights the three basic cases you might encounter:
It is either a list, then recourse, or a number, for everything else, just put it into the result list's tail (this also handles the empty list case). On the other hand you'll need red cuts for this solution, so it might be frowned upon by some purists.
If you don't want red cuts, you can replace the last clause with
addnumdeep(_,A,A):- !, \+ number(A), \+ A = [_|_].
If you don't want non-lists to be allowed, you could check with is_list if it is a list first and then call the proposed predicate.
I'd start with something that tells me whether a term is list-like or not, something along these lines:
is_list_like( X ) :- var(X) , ! , fail .
is_list_like( [] ) .
is_list_like( [_|_] ) .
Then it's just adding another case to your existing predicate, something like this:
add_num( _ , [] , [] ) . % empty list? all done!
add_num( N , [X|Xs] , [Y|Ys] ) :- % otherwise...
number(X) , % - X is numeric?
Y is X + N , % - increment X and add to result list
add_num( N , Xs , Ys ) % - recurse down
. %
add_num( N , [X|Xs] , [Y|Ys] ) :- % otherwise...
is_list_like( X ) , % - X seems to be a list?
! ,
add_num( N , X , Y ) , % - recurse down on the sublist
add_num( N , Xs , Ys ) % - then recurse down on the remainder
. %
add_num( N , [X|XS] , [Y|Ys] ) :- % otherwise (X is unbound, non-numeric and non-listlike
X = Y , % - add to result list
add_num( N , Xs , Ys ) % - recurse down
. %