The problem I'm trying to solve is as follows:
I'm given a sorted list where I must pair the first and last items in the list. Then I must pair the 2nd and (last-1) items in the list until the list is either empty or 1 element remains. Then I must return a list of the pairs.
The steps I decided to take for this problem was to first check if the list's length was greater than 1. If it wasn't, then that means we have a list of 0 or 1 elements.
Then I get the first and last items in the given list, delete them from the list, pair them, and then recursively call the same predicate on the new list. Once I've gone all the way down to 0/1 items, I then pop back up and append them to my return list.
The problem I'm having is that when I try to append the pair L = [first,last] to my return list, it errors out. My code is listed below.
T is my input list.
first/2 just gets the first item in the list. pair/3 strips away some info from P1 and P2 and then creates L = [P1,P2].
getMatches(T,K,ReturnList) :-
( length(T,Val),
Val > 1,
first(T,P1),
last(T, P2),
delete(T,P1,G),
delete(G,P2,H),
pair(P1,P2,L),
getMatches(H,K,ReturnList),
append(L,K,ReturnList)
; first(T,_),
K = []
).
An example use:
If T = [1, 2, 3, 4, 5] then
ReturnList = [[1,5], [2, 4]] should hold.
We define list_pairs/2 based on the commonly available list predicate append/3.
list_pairs([] , []).
list_pairs([_], []).
list_pairs([A,B|Xs0], [A-Z|Yss]) :-
append(Xs, [Z], [B|Xs0]),
list_pairs(Xs, Yss).
Note we do not represent a pair of X and Y as a list [X,Y], but rather as a compound X-Y. This convention is idiomatic, widespread, and more efficient, too!
Here's the most general query of list_pairs/2:
?- list_pairs(Es, Pss).
Es = [] , Pss = []
; Es = [_] , Pss = []
; Es = [A,B] , Pss = [A-B]
; Es = [A,_,B] , Pss = [A-B]
; Es = [A,B,C,D] , Pss = [A-D,B-C]
; Es = [A,B,_,C,D] , Pss = [A-D,B-C]
; Es = [A,B,C,D,E,F] , Pss = [A-F,B-E,C-D]
; Es = [A,B,C,_,D,E,F] , Pss = [A-F,B-E,C-D]
; Es = [A,B,C,D,E,F,G,H] , Pss = [A-H,B-G,C-F,D-E]
; Es = [A,B,C,D,_,E,F,G,H], Pss = [A-H,B-G,C-F,D-E]
...
This is a follow-up to this earlier answer and improves it by
avoiding the creation of useless choice-points and by
reducing the Big-O complexity from O(N2) to O(N).
list_pairs_lin([], []).
list_pairs_lin([X|Xs], XYs) :-
reverse(Xs, Ys),
ahead_keys_values_pairs(Xs, [X|Xs], Ys, XYs).
ahead_keys_values_pairs([], _, _, []).
ahead_keys_values_pairs([_|Fs0], [X|Xs], [Y|Ys], [X-Y|XYs]) :-
maybe_ahead(Fs0, Fs),
ahead_keys_values_pairs(Fs, Xs, Ys, XYs).
maybe_ahead([], []).
maybe_ahead([_|Xs], Xs).
Let's run some queries with SWI-Prolog 7.3.15!
Do we still get sound answers when using list_pairs_lin/2?
?- length(Es, N), numlist(1, N, Es), list_pairs_lin(Es, Pss).
N = 1, Es = [1] , Pss = []
; N = 2, Es = [1,2] , Pss = [1-2]
; N = 3, Es = [1,2,3] , Pss = [1-3]
; N = 4, Es = [1,2,3,4] , Pss = [1-4,2-3]
; N = 5, Es = [1,2,3,4,5] , Pss = [1-5,2-4]
; N = 6, Es = [1,2,3,4,5,6] , Pss = [1-6,2-5,3-4]
; N = 7, Es = [1,2,3,4,5,6,7] , Pss = [1-7,2-6,3-5]
; N = 8, Es = [1,2,3,4,5,6,7,8] , Pss = [1-8,2-7,3-6,4-5]
; N = 9, Es = [1,2,3,4,5,6,7,8,9], Pss = [1-9,2-8,3-7,4-6]
...
Yes! What about complexity?
?- set_prolog_flag(toplevel_print_anon, false).
true.
?- numlist(1, 5000, _Xs), time(list_pairs(_Xs,_)).
% 6,252,500 inferences, 2.302 CPU in 2.301 seconds (100% CPU, 2716404 Lips)
true ; % succeeds, but leaves behind useless choicepoint
% 2,503 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 1716259 Lips)
false. % terminates universally
?- numlist(1, 5000, _Xs), time(list_pairs_lin(_Xs,_)).
% 10,003 inferences, 0.003 CPU in 0.003 seconds (100% CPU, 3680523 Lips)
true. % succeeds deterministically
getMatches(List, ReturnList) :- % getMatches/2
getMatches(List, [], Answer),
reverse(Answer, ReturnList),
!.
getMatches(List, ListAns, ListAns) :- % getMatches/3
length(List, L),
L < 2.
getMatches([H | Tail], List, Ans) :-
last(Tail, Last),
delete(Tail, Last, NewTail),
append([[H, Last]], List, NewList),
getMatches(NewTail, NewList, Ans).
And
?- getMatches([1,2,3,4,5],X).
X = [[1, 5], [2, 4]].
Related
I'd like to have a Prolog predicate that can replace the nth item in the list with the first.
Example:
% replace(+List,+Counter,-New List, %-First Item).
?- replace([1,2,3,4,5],3,L,Z).
L = [1, 2, 1, 4, 5]
Z = 1
I don't know how to do this. Thanks for your help!
Try using the predicate nth1(Index, List, Item, Rest):
?- nth1(3, [1,2,3,4,5], Item, Rest).
Item = 3,
Rest = [1, 2, 4, 5].
?- nth1(3, List, 1, [1,2,4,5]).
List = [1, 2, 1, 4, 5].
Putting it all together:
replace(List, Index, NewList, First) :-
List = [First|_],
nth1(Index, List, _Removed, Rest),
nth1(Index, NewList, First, Rest).
Examples:
?- replace([1,2,3,4,5], 3, L, Z).
L = [1, 2, 1, 4, 5],
Z = 1.
?- replace([one,two,three,four,five], 4, NewList, First).
NewList = [one, two, three, one, five],
First = one.
Another method, slightly faster (replacing succ/2 with simple arithmetic helped performance):
replace_nth_with_first(Nth1, Lst, LstReplaced, First) :-
must_be(positive_integer, Nth1),
Lst = [First|_Tail],
replace_nth_with_first_(Nth1, Lst, LstReplaced, First).
% Keeping the arguments simple, to ensure that Nth1 = 1 matches
replace_nth_with_first_(1, Lst, LstReplaced, First) :-
!,
Lst = [_Head|Tail],
LstReplaced = [First|Tail].
replace_nth_with_first_(Nth1, [H|Lst], [H|LstReplaced], First) :-
Nth is Nth1 - 1,
replace_nth_with_first_(Nth, Lst, LstReplaced, First).
Result in swi-prolog:
?- replace_nth_with_first(3, [a, b, c, d, e], R, F).
R = [a,b,a,d,e],
F = a.
Performance comparison:
?- numlist(1, 2000000, L), time(replace_nth_with_first(1000000, L, R, First)).
% 1,000,004 inferences, 0.087 CPU in 0.087 seconds (100% CPU, 11428922 Lips)
% slago's
?- numlist(1, 2000000, L), time(replace_f(L, 1000000, R, First)).
% 2,000,011 inferences, 0.174 CPU in 0.174 seconds (100% CPU, 11484078 Lips)
Note the argument order, as per https://swi-prolog.discourse.group/t/split-list/4836/8
You might use append/3. Nice, concise, and declarative:
replace( [X|Xs] , 1 , [X|Xs], X ) . % replacing the first item in the list is a no-op
replace( Ls , I , L1 , X ) :- % for anything else...
I > 1 , % - the index must be greater than 1
J is I-1 , % - the length of the prefix is I-1
length( [X|Xs], J ) , % - construct an empty/unbound prefix list of the desired length
append( [X|Xs] , [_|Ys] , Ls ) , % - break the source list up into the desired bits
append( [X|Xs] , [X|Ys] , L1 ) % - and then put everything back together in the desired manner
. % Easy!
I have to write a predicate: double(X,Y) to be true when Y is the list consisting of each element of X
repeated twice (e.g. double([a,b],[a,a,b,b]) is true).
I ended with sth like this:
double([],[]).
double([T],List) :- double([H|T],List).
double([H|T],List) :- count(H, List, 2).
Its working fine for lists like [a,a,b] but it shouldnt... please help.
And i need help with another predicate: repeat(X,Y,N) to be true when Y is the list consisting of each element of X
repeated N times (e.g. repeat([a,b], [a,a,a,b,b,b],3) is true).
double([],[]).
double([I|R],[I,I|RD]) :-
double(R,RD).
Here's how you could realize that "repeat" predicate you suggested in the question:
:- use_module(library(clpfd)).
Based on if_/3 and (=)/3 we define:
each_n_reps([E|Es], N) :-
aux_n_reps(Es, E, 1, N).
aux_n_reps([], _, N, N). % internal auxiliary predicate
aux_n_reps([E|Es], E0, N0, N) :-
if_(E0 = E,
( N0 #< N, N1 #= N0+1 ), % continue current run
( N0 #= N, N1 #= 1 )), % start new run
aux_n_reps(Es, E, N1, N).
Sample queries1 using SICStus Prolog 4.3.2:
?- each_n_reps(Xs, 3).
Xs = [_A,_A,_A]
; Xs = [_A,_A,_A,_B,_B,_B] , dif(_A,_B)
; Xs = [_A,_A,_A,_B,_B,_B,_C,_C,_C], dif(_A,_B), dif(_B,_C)
...
How about fair enumeration?
?- length(Xs, _), each_n_reps(Xs, N).
N = 1, Xs = [_A]
; N = 2, Xs = [_A,_A]
; N = 1, Xs = [_A,_B] , dif(_A,_B)
; N = 3, Xs = [_A,_A,_A]
; N = 1, Xs = [_A,_B,_C] , dif(_A,_B), dif(_B,_C)
; N = 4, Xs = [_A,_A,_A,_A]
; N = 2, Xs = [_A,_A,_B,_B], dif(_A,_B)
; N = 1, Xs = [_A,_B,_C,_D], dif(_A,_B), dif(_B,_C), dif(_C,_D)
...
How can [A,B,C,D,E,F] be split into runs of equal length?
?- each_n_reps([A,B,C,D,E,F], N).
N = 6, A=B , B=C , C=D , D=E , E=F
; N = 3, A=B , B=C , dif(C,D), D=E , E=F
; N = 2, A=B , dif(B,C), C=D , dif(D,E), E=F
; N = 1, dif(A,B), dif(B,C), dif(C,D), dif(D,E), dif(E,F).
Footnote 1: Answers were reformatted to improve readability.
Ok for repeat/3 i have sth like this:
repeat1([],[],0).
repeat1([A|B],[X|T],Y):- repeat1(B,T,Z), Y is 1+Z.
repeat1([A1|B],[X1|T], Z) :- A1\=A, X1\=X, repeat1(B,T,Z).
This is the code for deleting or removing an element from a given list:
remove_elem(X,[],[]).
remove_elem(X,L1,L2) :-
L1 = [H|T],
X == H,
remove_elem(X,T,Temp),
L2 = Temp.
remove_elem(X,L1,L2) :-
L1 = [H|T],
X \== H,
remove_elem(X,T,Temp),
L2 = [H|Temp].
How can I modify it, so that I can delete every occurrence of a sub list from a list?
When I tried to put a list in an element, it only deletes the element and only once.
It should be this:
?- remove([1,2],[1,2,3,4,1,2,5,6,1,2,1],L).
L = [3,4,5,6,1]. % expected result
Inspired by #CapelliC's implementation I wrote the following code based on
and_t/3:
append_t([] ,Ys,Ys, true).
append_t([X|Xs],Ys,Zs,Truth) :-
append_aux_t(Zs,Ys,Xs,X,Truth).
append_aux_t([] ,_ ,_ ,_,false). % aux pred for using 1st argument indexing
append_aux_t([Z|Zs],Ys,Xs,X,Truth) :-
and_t(X=Z, append_t(Xs,Ys,Zs), Truth).
One append_t/4 goal can replace two prefix_of_t/3 and append/3 goals.
Because of that, the implementation of list_sublist_removed/3 gets a bit simpler than before:
list_sublist_removed([] ,[_|_] ,[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(append_t([L|Ls],Xs0,[X|Xs]),
(Zs = Zs0 , Xs1 = Xs0),
(Zs = [X|Zs0], Xs1 = Xs)),
list_sublist_removed(Xs1,[L|Ls],Zs0).
Still deterministic?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1].
Yes! What about the following?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3,4,5,6,1]).
X = [1,2] ; % succeeds with useless choice-point
false.
Nope. So there is still room for potential improvement...
This logically pure implementation is based on the predicates if_/3 and (=)/3.
First, we build a reified version of prefix_of/2:
prefix_of_t([],_,true).
prefix_of_t([X|Xs],Zs,T) :-
prefix_of_t__aux(Zs,X,Xs,T).
prefix_of_t__aux([],_,_,false).
prefix_of_t__aux([Z|Zs],X,Xs,T) :-
if_(X=Z, prefix_of_t(Xs,Zs,T), T=false).
Then, on to the main predicate list_sublist_removed/3:
list_sublist_removed([],[_|_],[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(prefix_of_t([L|Ls],[X|Xs]), % test
(Zs = Zs0, append([L|Ls],Xs0,[X|Xs])), % case 1
(Zs = [X|Zs0], Xs0 = Xs)), % case 2
list_sublist_removed(Xs0,[L|Ls],Zs0).
A few operational notes on the recursive clause of list_sublist_removed/3:
First (test), we check if [L|Ls] is a prefix of [X|Xs].
If it is present (case 1), we strip it off [X|Xs] yielding Xs0 and add nothing to Zs.
If it is absent (case 2), we strip X off [X|Xs] and add X to Zs.
We recurse on the rest of [X|Xs] until no more items are left to process.
Onwards to some queries!
The use case you gave in your question:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1]. % succeeds deterministically
Two queries that try to find the sublist that was removed:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[ 3,4,5,6,1]).
Sub = [1,2] ? ;
no
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[1,3,4,5,6,1]).
no
Next, let's find a suitable Ls in this query:
?- list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
% a lot of time passes ... and nothing happens!
Non-termination! This is unfortunate, but within expectations, as the solution set is infinite. However, by a-priori constraining the length of Ls, we can get all expected results:
?- length(Ls,_), list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
Ls = [ 3,4,5,6,1] ?
; Ls = [1,2, 3,4,5,6,1] ?
; Ls = [3, 1,2, 4,5,6,1] ?
; Ls = [3,4, 1,2, 5,6,1] ?
; Ls = [3,4,5, 1,2, 6,1] ?
; Ls = [3,4,5,6, 1,2, 1] ?
; Ls = [3,4,5,6,1, 1,2 ] ?
; Ls = [1,2, 1,2, 3,4,5,6,1] ? ...
<rant>
So many years I study Prolog, still it deserves some surprises... your problem it's quite simple to solve, when you know the list library, and you have a specific mode (like the one you posted as example). But can also be also quite complex to generalize, and it's unclear to me if the approach proposed by #repeat, based on #false suggestion (if_/3 and friends) can be 'ported' to plain, old Prolog (a-la Clocksin-Mellish, just to say).
</rant>
A solution, that has been not so easy to find, based on old-school Prolog
list_sublist_removed(L, S, R) :-
append([A, S, B], L),
S \= [],
list_sublist_removed(B, S, T),
append(A, T, R),
!
; L = R.
some test:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3, 4, 5, 6, 1].
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3, 4, 5, 6, 1]).
X = [1, 2].
?- length(X,_), list_sublist_removed(X,[1,2],[3, 4, 5, 6, 1]).
X = [3, 4, 5, 6, 1] ;
X = [3, 4, 5, 6, 1, 2, 1] ...
I'm trying to write a program in Prolog, which will insert an element into a certain position, so e.g.
?- ins(a, [1,2,3,4,5], 3, X).
X = [1,2,a,3,4,5].
I have the following code:
ins(X,[H|T],P,OUT) :-
length([T3],P),
concatenate(X,[H],T),
ins(...).
The problem is that it is inserting element X in given index from back (I even know where the problem is -> the length([T3],P) which is obviously the length of the list from back not from head) . I was trying to remember how much elements did I cut off and insert X when "number of cut off elements" = P, but I can't really write that in Prolog. Any ideas?
% ins(Val,List,Pos,Res)
ins(Val,[H|List],Pos,[H|Res]):- Pos > 1, !,
Pos1 is Pos - 1, ins(Val,List,Pos1,Res).
ins(Val, List, 1, [Val|List]).
The predicate fails if Pos = 0 or Pos > length(List) + 1
Let's state what you want here. For example you could say: "I want to split my input List after Position - 1 elements so that I can insert a new element there".
A direct traduction with append/3 (DCG would be better btw):
ins(Element, List, Position, Result) :-
PrefixLength is Position - 1,
length(Prefix, PrefixLength),
append(Prefix, Suffix, List),
append(Prefix, [Element], Temp),
append(Temp, Suffix, Result).
Or you could say: "I want to go through the elements of my List Position - 1 times without touching anything and then insert Element and then not touch anything again".
This time the direct traduction would be:
ins2(Element, List, 1, [Element|List]).
ins2(Element, [Head|Tail], Position, [Head|Result]) :-
Position > 1,
NewPosition is Position - 1,
ins2(Element, Tail, NewPosition, Result).
you could too state that: "My input List is a list equal to my Result one except it hasn't my Element as Positionth element." and realize that if you use swi-prolog, a predicate solves this instantly:
ins3(Element, List, Position, Result) :-
nth1(Position, Result, Element, List).
Bottom line is: state what the problem is clearly and the solution should appear in simple terms.
TL;DR: To insert item E at position I1 into list Es0, we do not need to write recursive code.
Instead, we can delegate the work (and the worries about getting it right, too!) to versatile auxiliary predicates, all of which are part of the Prolog prologue. To define ins_/4 we write:
ins_(E, Es0, I1, Es) :-
maplist(any_thing, Es, [_|Es0]),
append(Prefix, Suffix, Es0),
length([_|Prefix], I1),
append(Prefix, [E|Suffix], Es).
any_thing(_, _). % auxiliary predicate (used above)
Note that maplist(any_thing, Es, [_|Es0]) is equivalent to same_length(Es, [_|Es0]).
Sample queries1,2,3 using GNU Prolog version 1.4.4 (64-bit):
?- ins_(X, [a,b,c,d,e], N1, Xs).
N1 = 1, Xs = [X,a,b,c,d,e]
; N1 = 2, Xs = [a,X,b,c,d,e]
; N1 = 3, Xs = [a,b,X,c,d,e]
; N1 = 4, Xs = [a,b,c,X,d,e]
; N1 = 5, Xs = [a,b,c,d,X,e]
; N1 = 6, Xs = [a,b,c,d,e,X]
; false.
?- ins_(X, [a,b,c,d,e], 3, Xs).
Xs = [a,b,X,c,d,e]
; false.
?- ins_(X, Xs0, 3, [a,b,c,d,e]).
X = c, Xs0 = [a,b,d,e]
; false.
Let's not forget about the most general query!
?- ins(X, Es0, I1, Es).
Es0 = [], I1 = 1, Es = [X]
;
Es0 = [A], I1 = 1, Es = [X,A]
; Es0 = [A], I1 = 2, Es = [A,X]
;
Es0 = [A,B], I1 = 1, Es = [X,A,B]
; Es0 = [A,B], I1 = 2, Es = [A,X,B]
; Es0 = [A,B], I1 = 3, Es = [A,B,X]
;
Es0 = [A,B,C], I1 = 1, Es = [X,A,B,C]
; Es0 = [A,B,C], I1 = 2, Es = [A,X,B,C]
; Es0 = [A,B,C], I1 = 3, Es = [A,B,X,C]
; Es0 = [A,B,C], I1 = 4, Es = [A,B,C,X]
;
Es0 = [A,B,C,D], I1 = 1, Es = [X,A,B,C,D]
; ...
Fair enumeration of all solutions, OK!
EDIT:
I repeated the most general query with ins3/4 as defined
by #m09 in his answer on SWI-Prolog 7.3.11 and SICStus Prolog 4.3.2 (both feature the library predicate nth1/4).
I was surprised to see the underlying implementations of nth1/4 exhibit different procedural semantics (w.r.t. "fair enumeration"). See for yourself!
% SICStus Prolog 4.3.2 % SWI Prolog 7.3.11
% %
?- ins3(X, Es0, I1, Es). % ?- ins3(X, Es0, I1, Es).
I1 = 1, Es0 = [], Es = [X] % I1 = 1, Es = [X|Es0]
; % ; I1 = 2, Es0 = [_A|_Z],
I1 = 1, Es0 = [_A], Es = [X,_A] % Es = [_A,X|_Z]
; I1 = 2, Es0 = [_A], Es = [_A,X] % ; I1 = 3, Es0 = [_A,_B|_Z],
; % Es = [_A,_B,X|_Z]
I1 = 1, Es0 = [_A,_B], Es = [X,_A,_B] % ; I1 = 4, Es0 = [_A,_B,_C|_Z],
; I1 = 2, Es0 = [_A,_B], Es = [_A,X,_B] % Es = [_A,_B,_C,X|_Z],
; I1 = 3, Es0 = [_A,_B], Es = [_A,_B,X] % ; I1 = 5, Es0 = [_A,_B,_C,_D|_Z],
; % Es = [_A,_B,_C,_D,X|_Z]
... % ...
Footnote 1: All sample queries shown above terminate universally.
Footnote 2: The answers given by the GNU Prolog toplevel have been pretty-printed a little.
Footnote 3: The code presented above is used as-is, no additional library predicates are required.
ins(Element,List,Nth,Result) :-
length([_|L0],Nth),
append(L0,[_|R],List),
append(L0,[Element|R],Result).
I am trying to fill a list of given length N with numbers 1,2,3,...,N.
I thought this could be done this way:
create_list(N,L) :-
length(L,N),
forall(between(1,N,X), nth1(X,L,X)).
However, this does not seem to work. Can anyone say what I am doing wrong?
First things first: Use clpfd!
:- use_module(library(clpfd)).
In the following I present zs_between_and/3, which (in comparison to my previous answer) offers some more features.
For a start, let's define some auxiliary predicates first!
equidistant_stride([] ,_).
equidistant_stride([Z|Zs],D) :-
equidistant_prev_stride(Zs,Z,D).
equidistant_prev_stride([] ,_ ,_). % internal predicate
equidistant_prev_stride([Z1|Zs],Z0,D) :-
Z1 #= Z0+D,
equidistant_prev_stride(Zs,Z1,D).
Let's run a few queries to get a picture of equidistant_stride/2:
?- Zs = [_,_,_], equidistant_stride(Zs,D).
Zs = [_A,_B,_C], _A+D#=_B, _B+D#=_C.
?- Zs = [1,_,_], equidistant_stride(Zs,D).
Zs = [1,_B,_C], _B+D#=_C, 1+D#=_B.
?- Zs = [1,_,_], equidistant_stride(Zs,10).
Zs = [1,11,21].
So far, so good... moving on to the actual "fill list" predicate zs_between_and/3:
zs_between_and([Z0|Zs],Z0,Z1) :-
Step in -1..1,
Z0 #= Z1 #<==> Step #= 0,
Z0 #< Z1 #<==> Step #= 1,
Z0 #> Z1 #<==> Step #= -1,
N #= abs(Z1-Z0),
( fd_size(N,sup)
-> true
; labeling([enum,up],[N])
),
length(Zs,N),
labeling([enum,down],[Step]),
equidistant_prev_stride(Zs,Z0,Step).
A bit baroque, I must confess...
Let's see what features were gained---in comparison to my previous answer!
?- zs_between_and(Zs,1,4). % ascending consecutive integers
Zs = [1,2,3,4]. % (succeeds deterministically)
?- zs_between_and(Zs,3,1). % descending consecutive integers (NEW)
Zs = [3,2,1]. % (succeeds deterministically)
?- zs_between_and(Zs,L,10). % enumerates fairly
L = 10, Zs = [10] % both ascending and descenting (NEW)
; L = 9, Zs = [9,10]
; L = 11, Zs = [11,10]
; L = 8, Zs = [8,9,10]
; L = 12, Zs = [12,11,10]
; L = 7, Zs = [7,8,9,10]
...
?- L in 1..3, zs_between_and(Zs,L,6).
L = 3, Zs = [3,4,5,6]
; L = 2, Zs = [2,3,4,5,6]
; L = 1, Zs = [1,2,3,4,5,6].
Want some more? Here we go!
?- zs_between_and([1,2,3],From,To).
From = 1, To = 3
; false.
?- zs_between_and([A,2,C],From,To).
A = 1, From = 1, C = 3, To = 3 % ascending
; A = 3, From = 3, C = 1, To = 1. % descending
I don't have a prolog interpreter available right now, but wouldn't something like...
isListTo(N, L) :- reverse(R, L), isListFrom(N, R).
isListFrom(0, []).
isListFrom(N, [H|T]) :- M is N - 1, N is H, isListFrom(M, T).
reverse can be done by using e.g. http://www.webeks.net/prolog/prolog-reverse-list-function.html
So tracing isListTo(5, [1, 2, 3, 4, 5])...
isListTo(5, [1, 2, 3, 4, 5])
<=> isListFrom(5, [5, 4, 3, 2, 1])
<=> 5 is 5 and isListFrom(4, [4, 3, 2, 1])
<=> 4 is 4 and isListFrom(3, [3, 2, 1])
<=> 3 is 3 and isListFrom(2, [2, 1])
<=> 2 is 2 and isListFrom(1, [1])
<=> 1 is 1 and isListFrom(0, [])
QED
Since PROLOG will not only evaluate truth, but find satisfying solutions, this should work. I know this is a vastly different approach from the one you are trying, and apologize if your question is specifically about doing loops in PROLOG (if that is the case, perhaps re-tag the question?).
Here's a logically pure implementation of predicate zs_from_to/3 using clpfd:
:- use_module(library(clpfd)).
zs_from_to([],I0,I) :-
I0 #> I.
zs_from_to([I0|Is],I0,I) :-
I0 #=< I,
I1 #= I0 + 1,
zs_from_to(Is,I1,I).
Let's use it! First, some ground queries:
?- zs_from_to([1,2,3],1,3).
true.
?- zs_from_to([1,2,3],1,4).
false.
Next, some more general queries:
?- zs_from_to(Zs,1,7).
Zs = [1,2,3,4,5,6,7]
; false.
?- zs_from_to([1,2,3],From,To).
From = 1, To = 3.
Now, let's have some even more general queries:
?- zs_from_to(Zs,From,2).
Zs = [], From in 3..sup
; Zs = [2], From = 2
; Zs = [1,2], From = 1
; Zs = [0,1,2], From = 0
; Zs = [-1,0,1,2], From = -1
; Zs = [-2,-1,0,1,2], From = -2
...
?- zs_from_to(Zs,0,To).
Zs = [], To in inf.. -1
; Zs = [0], To = 0
; Zs = [0,1], To = 1
; Zs = [0,1,2], To = 2
; Zs = [0,1,2,3], To = 3
; Zs = [0,1,2,3,4], To = 4
...
What answers do we get for the most general query?
?- zs_from_to(Xs,I,J).
Xs = [], J#=<I+ -1
; Xs = [I], I+1#=_A, J#>=I, J#=<_A+ -1
; Xs = [I,_A], I+1#=_A, J#>=I, _A+1#=_B, J#>=_A, J#=<_B+ -1
; Xs = [I,_A,_B], I+1#=_A, J#>=I, _A+1#=_B, J#>=_A, _B+1#=_C, J#>=_B, J#=<_C+ -1
...
Edit 2015-06-07
To improve on above implementation of zs_from_to/3, let's do two things:
Try to improve determinism of the implementation.
Extract a more general higher-order idiom, and implement zs_from_to/3 on top of it.
Introducing the meta-predicates init0/3 and init1/3:
:- meta_predicate init0(2,?,?).
:- meta_predicate init1(2,?,?).
init0(P_2,Expr,Xs) :- N is Expr, length(Xs,N), init_aux(Xs,P_2,0).
init1(P_2,Expr,Xs) :- N is Expr, length(Xs,N), init_aux(Xs,P_2,1).
:- meta_predicate init_aux(?,2,+). % internal auxiliary predicate
init_aux([] , _ ,_ ).
init_aux([Z|Zs],P_2,I0) :-
call(P_2,I0,Z),
I1 is I0+1,
init_aux(Zs,P_2,I1).
Let's see init0/3 and init1/3 in action!
?- init0(=,5,Zs). % ?- numlist(0,4,Xs),maplist(=,Xs,Zs).
Zs = [0,1,2,3,4].
?- init1(=,5,Zs). % ?- numlist(1,5,Xs),maplist(=,Xs,Zs).
Zs = [1,2,3,4,5].
Ok, where do we go from here? Consider the following query:
?- init0(plus(10),5,Zs). % ?- numlist(0,4,Xs),maplist(plus(10),Xs,Zs).
Zs = [10,11,12,13,14].
Almost done! Putting it together, we define zs_from_to/2 like this:
z_z_sum(A,B,C) :- C #= A+B.
zs_from_to(Zs,I0,I) :-
N #= I-I0+1,
init0(z_z_sum(I0),N,Zs).
At last, let's see if determinism has improved!
?- zs_from_to(Zs,1,7).
Zs = [1,2,3,4,5,6,7]. % succeeds deterministically
If I understood correctly, the built-in predicate numlist/3 would do.
http://www.swi-prolog.org/pldoc/man?predicate=numlist/3