Prolog deep version predicate of adding to a list - prolog

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
. %

Related

prolog List Reverse

%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'm trying to remove a single occurrence of an element in a list

I'm using prolog and I'm trying to remove 1 element from the list. My append code works fine same with the if the element I am looking for is the first element in the list but it just says false if it is the second element in the list. Where am I going wrong
deleteFirst([A|X],B,Y,R):-
A\=B,
appendL(Y,A,[],Y1),
deleteFirst(X,B,Y1,R).
deleteFirst([A|X],A,Y,R):-
appendL(Y,X,[],R).
Try something like this:
% ---------------------------------------------
% remove the first X from List, yielding Result
% ---------------------------------------------
delete_first( X , List , Result ) :-
append( Prefix, [X|Suffix], List ) ,
! ,
append( Prefix, Suffix, Result ) .
The cut is needed to eliminate the choice point: otherwise, on backtracking, it will put the removed item back and try to find another matching X.
If you were to roll your own (I imagine that that is what your instructor wants), something like this, just a traversal of the list will do you:
delete_first( _ , [] , [] ) . % Remove this to fail if no matching X is found
delete_first( X , [X|Rs] , Rs ) :- % Once we find an X, we're done.
!. % - and eliminate the choice point
delete_first( X , [Y|Ys] , [Y|Rs] ) :- % Otherwise, put Y on the result list and recurse down
delete_first( X , Ys, Rs ) .

Prolog Ending a Recursion

countdown(0, Y).
countdown(X, Y):-
append(Y, X, Y),
Y is Y-1,
countdown(X, Y).
So for this program i am trying to make a countdown program which will take Y a number and count down from say 3 to 0 while adding each number to a list so countdown(3, Y). should produce the result Y=[3,2,1]. I can't seem the end the recursion when i run this and i was wondering if anyone could help me?
I cant seem to get this code to work any help? I seem to be getting out of global stack so I dont understand how to end the recursion.
Your original code
countdown( 0 , Y ) .
countdown( X , Y ) :-
append(Y, X, Y),
Y is Y-1,
countdown(X, Y).
has some problems:
countdown(0,Y). doesn't unify Y with anything.
Y is Y-1 is trying to unify Y with the value of Y-1. In Prolog, variables, once bound to a value, cease to be variable: they become that with which they were unified. So if Y was a numeric value, Y is Y-1 would fail. If Y were a variable, depending on your Prolog implementation, it would either fail or throw an error.
You're never working with lists. You are expecting append(Y,X,Y) to magically produce a list.
A common Prolog idiom is to build lists as you recurse along. The tail of the list is passed along on each recursion and the list itself is incomplete. A complete list is one in which the last item is the atom [], denoting the empty list. While building a list this way, the last item is always a variable and the list won't be complete until the recursion succeeds. So, the simple solution is just to build the list as you recurse down:
countdown( 0 , [] ) . % The special case.
countdown( N , [N|Ns] ) :- % The general case: to count down from N...
N > 0 , % - N must be greater than 0.
N1 is N-1 , % - decrement N
countdown(N1,Ns) % - recurse down, with the original N prepended to the [incomplete] result list.
. % Easy!
You might note that this will succeed for countdown(0,L), producing L = []. You could fix it by changing up the rules a we bit. The special (terminating) case is a little different and the general case enforces a lower bound of N > 1 instead of N > 0.
countdown( 1 , [1] ) .
countdown( N , [N|Ns] ) :-
N > 1 ,
N1 is N-1 ,
countdown(N1,Ns)
.
If you really wanted to use append/3, you could. It introduces another common Prolog idiom: the concept of a helper predicate that carries state and does all the work. It is common for the helper predicate to have the same name as the "public" predicate, with a higher arity. Something like this:
countdown(N,L) :- % to count down from N to 1...
N > 0 , % - N must first be greater than 0,
countdown(N,[],L) % - then, we just invoke the helper with its accumulator seeded as the empty list
. % Easy!
Here, countdown/2 is our "public predicate. It calls countdown/3 to do the work. The additional argument carries the required state. That helper will look like something like this:
countdown( 0 , L , L ) . % once the countdown is complete, unify the accumulator with the result list
countdown( N , T , L ) . % otherwise...
N > 0 , % - if N is greater than 0
N1 is N-1 , % - decrement N
append(T,[N],T1) , % - append N to the accumulator (note that append/3 requires lists)
countdown(N1,T1,L) % - and recurse down.
. %
You might notice that using append/3 like this means that it iterates over the accumulator on each invocation, thus giving you O(N2) performance rather than the desired O(N) performance.
One way to avoid this is to just build the list in reverse order and reverse that at the very end. This requires just a single extra pass over the list, meaning you get O(2N) performance rather than O(N2) performance. That gives you this helper:
countdown( 0 , T , L ) :- % once the countdown is complete,
reverse(T,L) % reverse the accumulator and unify it with the result list
. %
countdown( N , T , L ) :- % otherwise...
N > 0 , % - if N is greater than 0
N1 is N-1 , % - decrement N
append(T,[N],T1) , % - append N to the accumulator (note that append/3 requires lists)
countdown(N1,T1,L) % - and recurse down.
. %
There are several errors in your code:
first clause does not unify Y.
second clause uses append with first and third argument Y, which would only succeed if X=[].
in that clause you are trying to unify Y with another value which will always fail.
Y should be a list (according to your comment) in the head but you are using it to unify an integer.
You might do it this way:
countdown(X, L):-
findall(Y, between(1, X, Y), R),
reverse(R, L).
between/3 will give you every number from 1 to X (backtracking). Therefore findall/3 can collect all the numbers. This will give you ascending order so we reverse/2 it to get the descending order.
If you want to code yourself recursively:
countdown(X, [X|Z]):-
X > 1,
Y is X-1,
countdown(Y, Z).
countdown(1, [1]).
Base case (clause 2) states that number 1 yields a list with item 1.
Recursive clause (first clause) states that if X is greater than 1 then the output list should contain X appended with the result from the recursive call.

convert term to variable in prolog

I have a list of terms,
[g(_G543),g(_G548),g(_G553),g(_G558),g(_G558),g(_G553),g(_G548),g(_G543)]
How can I make it to
[_G543,_G548,_G553,_G558,_G558,_G553,_G548,_G543]
only left the variables.
I was trying
replace([],[]).
replace([g(X)|T1],[X|T2]):-
replace(T1,T2).
but it just returned a false, what should I do? Thanks
If your list looks like your example
[ g(A) , g(B) , g(C) , g(A) ... ]
something like this ought to do you:
extract_vars( [] , [] ) . % if the source list is exhausted, we're done
extract_vars( [g(V)|Xs] , [V|Vs] ) :- % otherwise...
var(V) , % - ensure we've got a var
! , % - eliminate the choice point
extract_vars( Xs , Vs ) % - recurse down
. %
extract_vars( [_|Xs] , Vs ) :- % anything else, we chuck
extract_vars( Xs , Vs ) %
. % Easy!
You could probably use findall\3, too:
extract_vars( Xs , Vs ) :-
findall( V , (member(g(V),Xs),var(V)) , Vs )
.
The underscore names eg. _G553 have no real relevance, so there's no need to maintain the exact names ?
In which case, assuming all list items are all g(..), there is no need to recurse through them.. just create a new list with the same length as the input list, but without the 'g' prefix:
X=[g(_G543),g(_G548),g(_G553),g(_G558),g(_G558),g(_G553),g(_G548),g(_G543)], length(X, Len), length(Y,Len).
X = [g(_G543), g(_G548), g(_G553), g(_G558), g(_G558), g(_G553), g(_G548), g(_G543)],
Len = 8,
Y = [_G3808, _G3811, _G3814, _G3817, _G3820, _G3823, _G3826, _G3829].
Here, length/2 is used to create a list of 'Len' items.

Prolog - solving problems with lists

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.

Resources