%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.
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 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
. %
How to implement flatten list in prolog ,with tail recursion ?
This is code for flatten/2 with simple recursion (that is mean without back-tracking):
flatten([], []).
flatten([L|Ls], FlatL) :-
!,
flatten(L, NewL),
flatten(Ls, NewLs),
append(NewL, NewLs, FlatL).
flatten(L, [L]).
?- flatten([1, [2,3], [4]], X).
X=[1,2,3,4].
I'm trying to do the same algorithm but with tail recursion (Accumulator). For exemple, the predicate sum/2 returns the addition of all member of the list, with backtracking:
sum([X],[X]).
sum([H|T],S) :- sum(T,S1), S is H + S1 .
the same algo with tail recursion is
sum1(L,S) :- sum1(L,0,S).
sum1([],Acc,Acc).
sum1([H|T],Acc,S) :- Acc1 is Acc+H, s(T,Acc1,S).
You might want to read up on tail recursion optimization
What Is Tail Call Optimization?
https://en.wikipedia.org/wiki/Tail_recursion
Tail recursion optimization/elimination has little to nothing to do with accumulators. It has to do with whether or not the current frame on the call stack can be reused. If it can, the recursive call is effectively converted into iteration. If it can't be reused, a new frame has to be pushed on the stack with the nasty side effect that [eventually] you will throw a stack overflow exception.
This is tail recursive and gets optimized into iteration:
write_list( [] ) .
write_list( [X|Xs] ) :-
write(X),nl,
write_list(Xs).
This is not:
factorial(1,1) .
factorial(N,F) :-
N > 1 ,
N1 is N-1 ,
factorial(N1,F1) ,
F is N1+F1 .
The difference is that in the former, no use is made of anything local following the recursive call, and so the stack frame can be reused. In the latter, the contents of the stack frame must be preserved, and so a new stack frame must be allocated for the recursive call.
However, the following should do the job for you.
flatten( Xs , Fs ) :- % to flatten a list of via an accumulator...
flatten( Xs , [] , Rs ) , % - invoke the worker predicate with the accumulator seeded as the empty list.
reverse(Rs,Fs) % - since the flattened list will be built in reverse order, you'll need to reverse it after all the work is done.
.
flatten( [] , Fs , Fs ) . % if the source list is exhausted, our work is done.
flatten( [X|Xs] , Ts , Fs ) :- % otherwise...
is_list(X) , % - if the head of the list is itself a list
! , % - eliminate the choice point.
flatten(X,Ts,T1) , % - flatten the sublist by invoking the worker predicate on the sublist
flatten(Xs,T1,Fs) % - and then continue
. %
flatten( [X|Xs] , Ts , Fs ) :- % finally, the list head must be unbound or some other non-list thing.
flatten(Xs,[X|Ts],Fs) % - prepend it to the accumulator and continue.
. %
is_list( X ) :- var(X) , ! , fail . % unbound variables are manifestly not lists.
is_list( [] ) . % but the empty lislt is.
is_list( [_|_] ). % and so is a non-empty list.
You should note that it's not completely tail recursive. Every time a nested list is encountered, it's got to save the current state, so it can continue from where it left off after the recursive call to flatten the sublist.
Can someone please help me in transforming this to match this updated requirement?
Define a predicate strikeDuplicates(X,Y) that succeeds if and only the list Y would
be obtained if one were to remove the second and subsequent occurrences of each element
from list X. (You might read strikeDuplicates (X,Y) as list X without duplicates
is list Y.) The strikeDuplicates/2 predicate need not work well when X is an
unbound variable.
I asked a similar question two days ago asking this:
Define a predicate strike(X,Y,Z) that succeeds if and only if the list Z would be
obtained if one were to remove all occurrences of element X from list Y. The
strike/3 predicate need not work well when Y is an unbound variable.
No one helped me so I had to do it by myself. That answer was this:
strike( _ , [] , [] ) .
strike( X , [X|T] , Z ) :- strike(X,T,Z) .
strike( X , [A|T] , [A|Z] ) :- dif(X,A) , strike(X,T,Z) .
dif(X,A).
A simple solution that doesn't preserve order is:
strike_duplicates([], []).
strike_duplicates([X| Xs], List) :-
( member(X, Xs) ->
strike_duplicates(Xs, List)
; List = [X| Tail],
strike_duplicates(Xs, Tail)
).
To preserve order, you need to keep track of the elements found so far while you traverse the list. A solution would be:
strip_duplicates(List, Set) :-
strip_duplicates(List, [], Set).
strip_duplicates([], _, []).
strip_duplicates([X| Xs], Found, List) :-
( member(X, Found) ->
strip_duplicates(Xs, Found, List)
; List = [X| Tail],
strip_duplicates(Xs, [X| Found], Tail)
).
The predicate member/2 is usually either a built-in predicate or available as a library predicate. Check your Prolog system documentation if necessary.
Well, the easy way would be to use the built-in predicate setof/3, but I suspect that's not what your professor wants.
Think about the problem for a second or two. A clear problem statement is often helpful (and in Prolog is often the solution itself):
To make the source list a set (unique elements) instead of a bag (allows duplication), you'll have to
Iterate over the source list
Track items you've already seen (the 'visited' list)
Add each item to the visited list only if the visited list doesn't already contain it.
Once you've done that you've got the desired result.
Here's a hint: a very common prolog idiom is the use of helper predicates that carry with it an accumulator. Often the helper predicate has the same functor, but a different arity. For example, to sum the values in a list (sum/2) we can use a helper sum/3 that carries an accumulator, seeded with 0:
sum(Xs,N) :- sum(Xs,0,N).
sum([],S,S).
sum([N|Ns],T,S) :-
T1 is T+N,
sum(Ns,T1,S)
.
You'll notice how unfication with the result is deferred until the final value has been computed.
You need to do something like that but using as an accumulator an [empty] list that will be extended with the unique values you discover.
Another hint: the built-in predicate member/2 will check if a term is a member of a list. It's written
member(X,[X|Xs]).
member(X,[_|Xs]) :- member(X,Xs).
So member(2,[1,2,3]) is true whilst member(2,[1,3]) is false.
Conversely, one can use member/2 to successively return each element of a list via backtracking: member(X,[1,2,3]) produces
X = 1 ;
X = 2 ;
X = 3 ;
false
Given those two notions, you should be able to figure out the solution. Come back and show us your code and we can help you. There is one other little gotcha, but I'm sure you'll figure it out.
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.