我有问题,因为我想生成列表的排列(在序言中),该列表包含n个零和24-n个无重复的数。我试过:findall(L, permutation(L,P), Bag)
,然后sort
删除重复,但这会导致堆栈溢出。任何人都有有效的方法吗?
而不是考虑列表,而考虑二进制数。该列表的长度为24个元素。如果所有这些元素均为1,则我们有:
?- X is 0b111111111111111111111111.
X = 16777215.
事实上的标准谓词between/3
可用于生成区间[0, 16777215]
中的数字:
?- between(0, 16777215, N).
N = 0 ;
N = 1 ;
N = 2 ;
...
仅其中一些数字满足您的条件。因此,您将需要过滤/测试它们,然后将传递的数字转换为等效的二进制列表表示形式。
按升序选择0到23之间的n个随机数。这些整数为您提供零的索引,并且所有配置都不同。关键是生成这些索引列表。
%
% We need N monotonically increasing integer numbers (to be used
% as indexes) from [From,To].
%
need_indexes(N,From,To,Sol) :-
N>0,!,
Delta is To-From+1,
N=<Delta, % Still a change to generate them
N_less is N-1,
From_plus is From+1,
(
(need_indexes(N_less,From_plus,To,SubSol),Sol=[From|SubSol]) % From is selected
;
(N<Delta -> need_indexes(N,From_plus,To,Sol)) % Alternatively, From is not selected
).
need_indexes(0,_,_,[]).
现在我们可以从可用的可能的索引中获取索引列表。
例如:
给我5个索引,从0到23(含0:):
?- need_indexes(5,0,23,Collected).
Collected = [0, 1, 2, 3, 4] ;
Collected = [0, 1, 2, 3, 5] ;
Collected = [0, 1, 2, 3, 6] ;
Collected = [0, 1, 2, 3, 7] ;
...
全部给他们:
?- findall(Collected,need_indexes(5,0,23,Collected),L),length(L,LL).
L = [[0, 1, 2, 3, 4], [0, 1, 2, 3, 5], [0, 1, 2, 3, 6], [0, 1, 2, 3, 7], [0, 1, 2, 3|...], [0, 1, 2|...], [0, 1|...], [0|...], [...|...]|...],
LL = 42504.
我们期望:(24!/((24-5)!* 5!))解决方案。
确实:
?- L is 20*21*22*23*24 / (1*2*3*4*5).
L = 42504.
现在唯一的问题是将每个解决方案(如[0, 1, 2, 3, 4]
)转换为0和1的字符串。这留作练习!