Prolog reversing a list - fast method - list

I'm trying to write a code in order to reverse a list in Prolog.
The result of my work is :
reverse(X,X).
reverse([X|Y],[H|X]):-
reverse(Y,H).
I ran this code on prolog but it doesn't work.
The fact that is seems correct to me and i cant find the errors.
Can you help me ?

My approach uses an empty accumulator list (as mentioned by joel76 in the comments) which gets filled with the elements of a list in reverse order one after another.
% reverse/2
% reverse(List,Result)
%
% Result will be the reversed list that gets returned
reverse(List,Result) :-
% call the accumulator method with the list and an empty placeholder list
reverse(List,[],Result).
% reverse/3
% reverse(List,Accumulator,ReverseList)
%
% >> stop rule for recursion
% -- checks whether initial List is empty (aka the reversing process is done)
% -- returns the ReversedList if completed, otherwise carry ReverseList over throughout the next iteration
reverse([],ReversedList,ReversedList).
% actual reversing method
reverse([Head|Tail],RestTail,ReverseList) :-
reverse(Tail,[Head|RestTail],ReverseList).
When executing these statements in SWI with e.g. reverse([a,b,c,d],X)., the idea behind it gets clearer:
?- reverse([a,b,c,d],X).
Call: (7) reverse([a,b,c,d], _G2273) ?
Call: (8) reverse([a,b,c,d],[], _G2273) ?
Call: (9) reverse( [b,c,d],[a], _G2273) ?
Call: (10) reverse( [c,d],[b,a], _G2273) ?
Call: (11) reverse( [d],[c,b,a], _G2273) ?
Call: (12) reverse( [],[d,c,b,a],_G2273) ?
Exit: (12) reverse( [],[d,c,b,a],[d,c,b,a]) ?
Exit: (11) reverse( [d],[c,b,a], [d,c,b,a]) ?
Exit: (10) reverse( [c,d],[b,a], [d,c,b,a]) ?
Exit: (9) reverse( [b,c,d],[a], [d,c,b,a]) ?
Exit: (8) reverse([a,b,c,d],[], [d,c,b,a]) ?
Exit: (7) reverse([a,b,c,d], [d,c,b,a]) ?
X = [d,c,b,a].
Explanation: Imagine the initial list being a stack of elements. Each of the initial list's elements get cut from itself by doing list-splitting like [Head|Tail]. Head will be added to the accumulator list by making a new list [Head|ReverseTail]. RevserseTail is simply the current content of the accumulator list, so the currently reversed list gets the initial list's Head added at first position, while the tail follows after. The following step will be to call reverse/3 recursively with the Tail part as the remainders of the initial list, [Head|ReverseTail] as the current reverse list, and ReverseList which has no other purpose other than serving as the value to be returned when the process is finished.
This will be repeated until all elements of the initial list were added to the accumulator one by one and the initial list is empty, which is when the recursion stops and the reversed list is returned.

Related

Prolog: is there any way to generate the following items from a list?

I want to develop a predicate in prolog called next, which given a list returns another list with the N elements following the last value of the list where N is the size of the main list. For example: next([1,2,3,4], R).
will return R = [5,6,7,8]. or: next([11,12,13], R). It will return R = [14,15,16].
The problem I have is that if I iterate over the main list until I am left with its last element and start adding the next one to it to the result list, I don't know how many times I should iterate since I don't know what the length of the main list was.This is why my algorithm goes into a loop.
next([], []).
next([X], [X1|Res]) :- X1 is X + 1, next3([X1],Res),!.
next([H|T], [X]) :- next3(T, X).
How about this.
Here we use Constraint Logic Programming to constraint the elements of the result list to be increasing-monotonically-by-1 but just set them to actual values (in one instruction) once we know the last element of the input list.
We also use an open list (a list with an unbound fin) instead of append/3 to grow the output list at its end efficiently. This idiom called "using a difference list".
Finally we add test cases.
:- use_module(library(clpfd)).
% ---
% Called by the customer
% ---
nextor([],[]) :- !. % Empty input list means no work to do!
nextor([X|Xs],Out) :- % The input list contains at least 1 element
assertion(integer(X)), % This is for stating what we assume
OpenList = [K|Fin], % We will create a list of fresh variables; in order
% _to append easily, the list is kept "open", i.e. its tail end
% _is not [] as in a proper list but an unbound variable
% _(namely, Fin). The first element is as yet undefined,
% it is the fresh variable K.
assertion(\+is_list(OpenList)), % Not a list at present time.
nextor_w(X,Xs,[K|Fin],LastFin,LastX), % Processing the list with the first element X already
% _separated out (for assertions). To grow the OpenList at
% _its end, we just need Fin (we don't care about that list's
% Tip when we grow it at the end). Finally, to communicate
% the last Fin set up in the depth of the recursion to this
% call place, use LastFin. The last X found will be in LastX.
LastFin=[], % The open list is close (made proper list) by setting its
% _final Fin to [].
assertion(is_list(OpenList)), % Yes, it is a list now!
K #= LastX+1, % Now that LastX is known, we know K too.
% _The constraint propagates down the list, fixing the still
% unbound variables in OpenList (which is now a closed list).
Out = OpenList. % Unify for result.
% ---
% Does the recursion down the input list
% ---
nextor_w(Xp,[],[_|Fin],Fin,Xp) :- !. % At the end of recursion, communicate the "last X" and the
% and the "latest Fin" back to the caller.
nextor_w(Xp,[X|Xs],[K|Fin],FinOut,XpOut) :-
assertion(Xp+1 =:= X), % The input list is assumed to increase monotonously.
Kn #= K+1, % Next K is constrained to be previous K + 1,
Fin = [Kn|NewFin], % The Fin of the open list is set to a new list cell, with a new Fin
nextor_w(X,Xs,[Kn|NewFin],FinOut,XpOut).
% ---
% Testing
% ---
:- begin_tests(nextor).
test("empty list" ,true(R == [])) :-
nextor([],R).
test("1-elem list",true(R == [2])) :-
nextor([1],R).
test("2-elem list",true(R == [3,4])) :-
nextor([1,2],R).
test("3-elem list",true(R == [4,5,6])) :-
nextor([1,2,3],R).
:- end_tests(nextor).
And so:
?- run_tests.
% PL-Unit: nextor .... done
% All 4 tests passed
true.
How about doing:
next(In,Out) :-
length(In,N),
maplist(plus(N),In,Out).
Uses length/2 and maplist/3. This works for the examples in your question - next([1,2,3,4],R). and next([11,12,13],R). - but only because the lists contain consecutive numbers. next([23,2,18],R). will unify R with [26,5,21].
Or:
next(In,Out) :-
length(In,N),
last(In,LastValue),
MinValue is LastValue+1,
MaxValue is LastValue+N,
numlist(MinValue,MaxValue,Out).
Uses last/2 and numlist/3. With this approach next([23,2,18],R). will unify R with [19,20,21].
This works fine for me:
next(Xs,Ys) :-
next(Xs,[_],Ys).
next([_],[],[]).
next([X],[_|Q],[X1|R]) :-
X1 is X + 1,
next([X1],Q,R).
next([_|T],Q,R) :-
next(T,[_|Q],R).
As it runs down the list it is building up a second list. When it finds the end of the first list it then runs down the second list building the output.
I got this kind of output:
?- next([1,2,3,7,8],W).
W = [9, 10, 11, 12, 13] .

Prolog palindrome

I'm trying to write a palindrome function in Prolog. I know I could just use something like
palindrome(List) :- reverse(List, List).
But I'm trying to figure out a way without using the built in reverse. I've created my own reverse rule:
rev([], []).
rev([H|T], X) :- rev(T, Y), append(Y, [H], X).
And what I'd like is, given a list, say [a,b,c,d], I'd like to do something like "X = rev([a,b,c,d]), but I'm really not sure whether this is possible in Prolog.
If it is, the way I would write my palindrome function would be something like:
palindrome(List) :- append(L1, rev(L1), List).
Is it possible to do what I'm trying to do - i.e. X = rev([a,b,c,d])?.
Thanks.
Palindromes are lists that read the same from front to back and from back to front. So the example you have given, [a,b,c,d] and it's reversal, constitute a palindrome if the first is directly followed by the second: [a,b,c,d,d,c,b,a]. Since you are trying to describe specific kinds of lists, it is very tempting to use Prolog DCGs for the task. With them you can define palindromes like so:
palindrome(X) :-
phrase(palindrome,X).
palindrome --> % base case for even number of elements
[].
palindrome --> % base case for odd number of elements
[A].
palindrome --> % general case: a palindrome is
[A], % some element A...
palindrome, % ... followed by a palindrome ...
[A]. % ... followed by element A
The most general query is producing palindromes with variables for each position:
?- palindrome(P).
P = [] ? ;
P = [_A] ? ;
P = [_A,_A] ? ;
P = [_A,_B,_A] ? ;
P = [_A,_B,_B,_A] ? ;
P = [_A,_B,_C,_B,_A] ?
...
Or alternatively you can test if a specific list is a palindrome:
?- palindrome("rats live on no evil star").
yes
?- palindrome([1,2,3,2,1]).
yes
?- palindrome([a,b,c,d]).
no
?- palindrome([a,b,c,d,d,c,b,a]).
yes
If you insist on using list reversal you can define the relation like so:
list([]) -->
[].
list([X|Xs]) -->
[X],
list(Xs).
invlist([]) -->
[].
invlist([X|Xs]) -->
invlist(Xs),
[X].
palindrome --> % a paindrome is
list(L), % a list followed
invlist(L). % by its reversal
palindrome --> % a palindrome is
list(L), % a list followed by
[_A], % some element
invlist(L). % then by the reversed list
The first of the above queries produces the answers in a different order now, namely the solutions with an even number of elements first:
?- palindrome(P).
P = [] ? ;
P = [_A,_A] ? ;
P = [_A,_B,_B,_A] ? ;
P = [_A,_B,_C,_C,_B,_A] ?
...
The other example queries yield the same result. However, the first definition seems to be clearly preferable to me. Not only because it is shorter as there is no need for additional DCG rules but also because it is producing the results in a fair order: empty list, one element, two elements, ... With the second version you get all the lists with an even number of elements first and there are infinitely many of those. So you never get to see a solution with an odd number of elements with the most general query.

Possible list permutation using a given formula

I am trying to get my head wrap around lists in Prolog. To do this I am trying to create a sort of game. You pass in a list of numbers 1-9 that can be repeated, the list can be any length. The rules are that starting from the first element(e) you can only move to e+2 or e+3 until you get to the end. The goal is to "land" on the highest numbers. In essence it is kind of like hopscotch. The problem I am running into is determining all the possible permutation for paths. So far I have the following.
paths([], []). %empty list returns empty list
paths([X], [X]). %list with one element returns that one element
paths([X1, X2], [X1]). %list with 2 elements returns the first element
paths([X1, X2, X3], [X1,X3]). %list with three elements returns the first and third element
paths() :- % the recursive case for a list with 4+ elements
An list to use would be: [1,2,3,4,5,6,8,7,9,3,6,5,7,8,9]
I need to determine all possible paths using the rule mentioned about. I wish lists could be indexed in Prolog :(
Any logic guidance would be appreciated.
The requirements aren't completely clear, but it seems that:
The second argument is required to have the same first element as the
first argument (you "hop" on the first "square" first always, using
your hopscotch metaphore)
You aren't requiring that the last element of the first list be the
last element of the second list (you aren't requiring that you "land
on" the last "square").
An empty list succeeds with an empty list result (rather than just failing on an empty list - which is another valid approach).
Then this could be implemented as follows. You do not need many explicit 2- and 3-element list cases since they are handled by the recursive clause and simpler base cases.
path([], []).
path([X], [X]).
path([X,_|T], [X|R]) :- % hop over 1 element
path(T, R).
path([X,_,_|T], [X|R]) :- % hop over 2 elements
path(T, R).
For a simple example:
| ?- path([1,2,3,4,5,6], R).
R = [1,3,5] ? ;
R = [1,3,6] ? ;
R = [1,4,6] ? ;
R = [1,4]
yes
If I don't have your requirements exactly right, you should be able to adjust this to suit your needs as it shows how to handle a recursive case. It also sounds like you are headed in the direction of trying to optimize the values in your hops, which I shall also leave as an exercise.
This can also be done with a DCG (definite clause grammar)
path([]) --> [].
path([X]) --> [X].
path([X|T]) --> ([X,_] | [X,_,_]), path(T).
Which would be exercised:
| ?- phrase(path(R), [1,2,3,4,5,6]).
R = [1,3,5] ? ;
R = [1,3,6] ? ;
R = [1,4,6] ? ;
R = [1,4] ? ;
(1 ms) no
| ?-
In light of the extra requirement that the last step taken must be one that falls within the list, here is an updated version of the path/2 predicate:
path([], []).
path([X], [X]).
path([X,_], [X]).
path([X,_,Y|T], [X|R]) :- % hop over 1 element
path([Y|T], R).
path([X,_,_,Y|T], [X|R]) :- % hop over 2 elements
path([Y|T], R).
I think that there is a reason to avoid indexing: simplicity. If you decompose your problem, maybe you could start writing a step/3 predicate like
step([_,X|T],X,T).
step([_,_,X|T],X,T).
and then
paths([],[]).
paths(L,[X|Xs]) :- step(L,X,T), paths(T,Xs).
note: I don't understand very well your game, some example of playground and solution would be welcome.
%passing in a list and return all possible paths using K+2 or K+3 with K being the first element of the list.
%empty list returns empty list
%list with one element returns that one element
%list with 2 elements returns the first element
%list with three elements returns the first and third element
%list with four/four+ elements needs to be called recursively, prefix them with the first element and append them together
%RL means ReturnList
%FL means FinalList
%List is the appended list containing all the paths
paths([], []).
paths([X], [[X]]).
paths([X1, X2], [[X1]]).
paths([X1, X2, X3], [[X1,X3]]).
paths([X1, X2, X3, X4 | T], List) :-
paths([X3,X4|T], RL), paths([X4|T], RL2),
prefix_all(X1, RL, FL1), prefix_all(X1, RL2, FL2),
append(FL1, FL2, List).
So if run with the list [1,2,3,4,5] is would produce the following:
| ?- paths([1,2,3,4,5],X).
X = [[1,3,5],[1,4]] ? ;
no

PROLOG: Keep list in recursion

So, I've spent a lot of my time trying to figure this out without almost no progress. Hope you could help me.
The goal is, to take a list like this(lets call it baselist): [[[feesc,11],[podshare,11]],[[feesc,11]],[]]. And make it become this: [[feesc,22],[podshare,11]].
I have a predicate responsible to add or sum to the resulting list. Here is the code:
place_key([Key,Value], [], [Key,Value]).
place_key([Key,Value], [[Key,V]|Rest], [[Key,V1]|Rest]) :- V1 is V+Value.
place_key([Key,Value], [[K,V]|Rest], [[K,V]|List2]) :- Key \= K, place_key([Key,Value], Rest, List2)."
If I manually call this method, for simulating the recursion, it works exactly how I want.
Example:
place_key([feesc,11], [], R), place_key([feesc,11],R,J).
So J is = [[feesc,22]].
Expected result is correct.
The problem is to that with recursion.
So basically what I need to do is: iterate through the baselist, when reaching each key/par list, call place_key and keep it in the stack so the recursion keeps it until the last.
Just to point out, I don't want to append, I just need the latest result from place_key.
What I have done so far:
fe([HO|T],NL,R) :- write(HO), place_key(HO,NL,RESULT), fe(T,RESULT,R).
fe(S,R):- fe(S,[],R).
fe([],[]).
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
When I run:
[trace] 57 ?- feg([[[feesc,11]],[[feesc,11]]],R).
Call: (6) feg([[[feesc, 11]], [[feesc, 11]]], _G21384) ? creep
Call: (7) fe([[feesc, 11]], _G21484) ? creep
Call: (8) fe([[feesc, 11]], [], _G21485) ? creep
Call: (9) place_key([feesc, 11], [], _G21485) ? creep
Exit: (9) place_key([feesc, 11], [], [[feesc, 11]]) ? creep //Until here, I think this is correct.
Call: (9) fe([], [[feesc, 11]], _G21494) ? creep
Fail: (9) fe([], [[feesc, 11]], _G21494) ? creep
Redo: (9) place_key([feesc, 11], [], _G21485) ? creep
Fail: (9) place_key([feesc, 11], [], _G21485) ? creep
Fail: (8) fe([[feesc, 11]], [], _G21485) ? creep
Fail: (7) fe([[feesc, 11]], _G21484) ? creep
Fail: (6) feg([[[feesc, 11]], [[feesc, 11]]], _G21384) ? creep
false.
What am I doing wrong?
The problem in your case is that you don't define a base-case for fe/3. As you can see, except for your place_key predicate, you also have the following:
fe([HO|T],NL,R) :- write(HO), place_key(HO,NL,RESULT), fe(T,RESULT,R).
fe(S,R):- fe(S,[],R).
fe([],[]).
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
I'll try to make this a little more readable, so you can see what's going on:
% fe/3 cases
fe([Head|Tail],Current,Result) :- write(Head), place_key(Head,Current,TempResult), fe(Tail,TempResult,Result).
% fe/2 cases
fe(S,R):- fe(S,[],R).
fe([],[]).
%% this case above is never used, as the first case always matches
% recursive and base cases for feg
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
You should rewrite this as following:
fe([],Result,Result).
This is your base case, if the list is empty, the result in-between is equal to the final result. Prolog always tries the first possible match first, so always set your base-case on top.
fe([Head|Tail],Current,Result) :- write(Head), place_key(Head,Current,TempResult), fe(Tail,TempResult,Result).
This is your recursive case, as you had before, which we will put below our base case.
We can drop the second fe/2 case, as the first case always matches and we rewrite to fe/3 anyway, which can handle all cases.
fe(S,R):- fe(S,[],R).
Below are your existing feg/2 cases. Here is also an error, because after your first fe/2-predicate, the RESULT-variable has a value, but it still needs to be able to unify with the call feq(T,RESULT), which will produce a different value. I'll leave this as an exercise.
feg([HO,T],R) :- fe(HO,RESULT), feg(T,RESULT), R = RESULT.
feg([],[]).
Keep your key/pairs as a tuple, a simple term with an arity of 2. Something like K-V or K:V or even tuple(K,V) is preferable to [K,V]. There's a simple reason for this:
K-V, K:V and tuple(K,V) all map to simple structures: -(K,V), :(K,V) and tuple(K,V) respectively, while...
[K,V] is syntactic sugar for a rather more complicated structure .(K,.(V,[])).
Further, you might realize that your key/value pairs are hard to distinguish from the nested list-of-lists. Keeping the Key/Value pairs as tuples makes that distincation clear.
So, let us assume your key/value pairs are represented as K:V. It sounds to me that what you're essentially wanting to do is walk your nested list-of-lists (essentially, a tree), enumerate the key/value pairs it contains and produce the set (unique). Here's one way to do that.
First, a simple predicate to identify a non-empty list:
nonnempty_list( L ) :- nonvar(L) , L = [_|_] .
Then, a simple predicate to walk the nested list of lists and enumerate each key/value pair it finds:
visit( [ K:R | Ls ] , K:R ) . % succeed if the head of the list is a key/value pair.
visit( [ L | Ls ] , KVP ) :- % otherwise...
nonempty_list(L) , % - if the head is a non-empty list ,
visit( L , KVP ) % - visit it.
. %
visit( [_|Ls] , KVP ) :- % finally...
visit( Ls , KVP ) % - recurse down on the tail.
. %
Then you can use the magic of setof/3 to get what you want:
flattened_set( LoL , KVPs ) :-
setof( KVP , visit(LoL,KVP) , KVPs )
.

Sum of elements in list in Prolog

list_sum([], 0).
list_sum([Head | Tail], TotalSum) :-
list_sum(Tail, Sum1),
Total = Head + Sum1.
This code returns true. If I replace Total = Head + Sum1 with Total is Head + Sum1, then it will return the value. But what I should replace it with to get the result like this:
?- list_sum([1,2,0,3], Sum).
Sum = 1+2+0+3 ; % not to return value 6!!!
The answer is simple:
sum_list([], 0).
sum_list([H|T], Sum) :-
sum_list(T, Rest),
Sum is H + Rest.
This code works in only one direction - this means - it does not allow you to generate lists with that specific sum. But since the set of such lists is infinite, that would not be practical anyways.
Note that in the second clause of your procedure TotalSum is never instantiated. You should have received a warning by the interpreter when consulting your code.
Here's my suggestion:
list_sum([Item], Item).
list_sum([Item1,Item2 | Tail], Total) :-
list_sum([Item1+Item2|Tail], Total).
The first clause deals with the base case, when there is only one element left in the list, that is your result.
The second clause deals with the recursion step. It grabs the first two items of the list and performs a recursive call replacing those two items with a new term Item1+Item2.
The program is
list_sum([],0).
list_sum([Head|Tail], TotalSum):-
list_sum(Tail, Sum1),
TotalSum is Head+Sum1.
now if the query is
?- list_sum([1,2,3,4], Sum).
answer is
Sum = 10
In Prolog (+)/2 is a binary infix operator. This allows us to write A+B instead of +(A,B).
?- current_op(_,yfx,+). % left-associative binary infix operator
true.
(+)/2 associates to the left, so 1+2+3 is a short for (1+2)+3.
(.)/2 associates to the right, so [1,2,3] is short for .(1,.(2,.(3,[]))).
To get parenthesization right, we use an auxiliary predicate with an extra "accumulator" argument:
list_sum([X|Xs],S) :-
list_sum0_sum(Xs,X,S).
list_sum0_sum([], S ,S).
list_sum0_sum([X|Xs],S0,S) :-
list_sum0_sum(Xs,S0+X,S).
Sample query:
?- list_sum([1,2,0,3],S).
S = 1+2+0+3.
If you want to transform a list of numbers into an additive expression, from
[1,2,3]
to
1 + 2 + 3
you could do something like this, using something like a difference list:
list_to_additive_expr( [] , 0 ).
list_to_additive_expr( [X|Xs] , X + RHS ) :-
sum_of( Xs , RHS ).
Alternatively, you could use an accumulator:
list_to_additive_expr( Xs , Expr ) :-
list_to_additive_expr( Xs , 0 , Expr )
.
list_to_additive_expr( [] , Expr , Expr ) .
list_to_additive_expr( [X|Xs] , RHS , Expr ) :-
sum_of( Xs , X + RHS , Expr )
.
I believe you'll find the first style is not properly tail recursive and so won't get optimized into a loop via tail recursion optimization (TRO) — and so, if the list is sufficiently long, will get a stack overflow. The second approach should have TRO applied and should work for lists of any length.
What is TRO, you might ask? Here's Wikipedia with an answer for you:
In computer science, a tail call is a subroutine call that happens inside another
procedure and that produces a return value, which is then immediately returned by the
calling procedure. The call site is then said to be in tail position, i.e. at the end of
the calling procedure. If a subroutine performs a tail call to itself, it is called
tail-recursive. This is a special case of recursion.
Tail calls are significant because they can be implemented without adding a new stack
frame to the call stack. Most of the frame of the current procedure is not needed any
more, and it can be replaced by the frame of the tail call, modified as appropriate
(similar to overlay for processes, but for function calls). The program can then jump to
the called subroutine. Producing such code instead of a standard call sequence is called
tail call elimination, or tail call optimization.