我想制作一个从类型[a,b,c]创建列表的生成器,从[0,0,0]开始,下一个是[0,0,1],[0,1,0 ],[1,0,0],[0,1,1],[1,0,1],[1,1,0],[1,1,1],[1,1,2]和所以无限。
对不起,我用长长的例子说了这些,我只是不知道如何用英语解释它。
如果我有一个范围(让我们说它达到10)我会像这样使用:
genCombo([A,B,C]):-
between(0,10,A),
between(0,10,B),
between(0,10,C).
但是当它无限时,我不知道该怎么做。
答案 0 :(得分:1)
between/3
将原子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.
使用约束最好能够以所请求的顺序生成列表...从头到尾,我想出了以下不使用约束的实现:
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).
使用示例:
?- 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] ;
答案 1 :(得分:1)
我限制了范围,以获得干净的显示,但你可以用inf替换3。当然,不要把连接放在findall :) 这个想法是只有一个发电机运行到无穷大,其他两个(或任何你想要的)受到该值的限制......
?- 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]
...
答案 2 :(得分:1)
以下我们使用clpfd。
:- use_module(library(clpfd)).
首先,考虑一下:
?- 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].
接下来,概括sum(Zs,#=,3)
和
使用length(_,Sum)
公平的列举......我们已经完成了
?- 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] ...