Prologue list of number generators
I would like to create a generator that creates a list from type [a, b, c] starting at [0,0,0], the next one is [0,0,1], [0,1,0], [1,0 , 0], [0,1,1], [1,0,1], [1,1,0], [1,1,1], [1,1,2] and so on to infinity.
I'm sorry I said this with a long example. I just don't know how to explain this in English.
If I had a range (say up to 10), I would use the following:
genCombo([A,B,C]):-
between(0,10,A),
between(0,10,B),
between(0,10,C).
But when he goes on forever, I don't know what to do.
source to share
I have limited the range to get a clean display, but you can replace 3 with inf. Of course, don't put conjunction in findall :) The idea is that only one of the generators runs indefinitely, the other two (or whatever you want) are limited to this value ...
?- findall([B,C,A], (between(0, 3, A), between(0, A, B), between(0, A, C)), L), maplist(writeln,L).
[0,0,0]
[0,0,1]
[0,1,1]
[1,0,1]
[1,1,1]
[0,0,2]
[0,1,2]
[0,2,2]
[1,0,2]
[1,1,2]
[1,2,2]
[2,0,2]
[2,1,2]
[2,2,2]
[0,0,3]
[0,1,3]
[0,2,3]
[0,3,3]
...
source to share
between/3
takes an atom as its second argument inf
:
?- between(0, inf, X). X = 0 ; X = 1 ; X = 2 ; X = 3 ; X = 4 ; X = 5 ; X = 6 ; X = 7 ; X = 8 ; X = 9 ; X = 10 ; X = 11 ; Etc.
Creating lists in the requested order is probably best achieved with constraints ... From the top of my chapter, I provide the following implementation, which does not use constraints:
go([A,B,C]):-
between(0, inf, X1),
succ(X1, X2),
member(A, [X1,X2]),
member(B, [X1,X2]),
member(C, [X1,X2]),
\+ (A == X2, B == X2, C == X2).
Usage example:
?- go(L). L = [0, 0, 0] ; L = [0, 0, 1] ; L = [0, 1, 0] ; L = [0, 1, 1] ; L = [1, 0, 0] ; L = [1, 0, 1] ; L = [1, 1, 0] ; L = [1, 1, 1] ; L = [1, 1, 2] ;
source to share
In the future, we use clpfd...
:- use_module(library(clpfd)).
Consider first:
? - Zs = [_, _, _], Zs ins 0..sup, sum (Zs, # =, 3 ), labeling ([], Zs). Zs = [0,0,3] ; Zs = [0,1,2] ; Zs = [0,2,1] ; Zs = [0.3.0] ; Zs = [1,0,2] ; Zs = [1,1,1] ; Zs = [1,2,0] ; Zs = [2,0,1] ; Zs = [2,1,0] ; Zs = [3.0.0].
Next, generalize sum(Zs,#=,3)
and use length(_,Sum)
for a fair listing ... and we've done
? - length (_, Sum) , Zs = [_, _, _], Zs ins 0..sup, sum (Zs, # =, Sum ), labeling ([], Zs). Sum = 0, Zs = [0,0,0] ; Sum = 1, Zs = [0,0,1] ; Sum = 1, Zs = [0,1,0] ; Sum = 1, Zs = [1,0,0] ; Sum = 2, Zs = [0,0,2] ; Sum = 2, Zs = [0,1,1] ; Sum = 2, Zs = [0,2,0] ; Sum = 2, Zs = [1,0,1] ; Sum = 2, Zs = [1,1,0] ; Sum = 2, Zs = [2,0,0] ; Sum = 3, Zs = [0,0,3] ; Sum = 3, Zs = [0,1,2] ; Sum = 3, Zs = [0,2,1] ; Sum = 3, Zs = [0,3,0] ; Sum = 3, Zs = [1,0,2] ; Sum = 3, Zs = [1,1,1] ; Sum = 3, Zs = [1,2,0] ; Sum = 3, Zs = [2,0,1] ; Sum = 3, Zs = [2,1,0] ; Sum = 3, Zs = [3,0,0] ; Sum = 4, Zs = [0,0,4] ...
source to share