假设您有以下谓词:
random_int(X/Y):-
random(1,100,X),
random(1,100,Y),
X\=Y.
如何使用此谓词的结果填充大小为n的列表?
我尝试了以下代码,但只有在第一次尝试时random_int(X)为true时才会填充列表,即它不会回溯以尝试X和Y的其他组合。
findall(X,(between(1,N,_), random_int(X)),L).
答案 0 :(得分:1)
您可以使用findall/3
执行此操作:
random_list(N, L) :-
findall(X, (between(1,N,_), random(50,100,X)), L).
另一种简洁的方法是:
random_list(N, L) :-
length(L, N),
maplist(random(50, 100), L).
结果是:
| ?- random_list(5, L).
L = [69,89,89,95,59]
yes
| ?-
一般情况下,如果您有一个谓词p(X1,X2,...,Xn,Y)
,并且要使用对Y
的连续调用填充结果p/(n+1)
的列表,则可以使用length(List, Length)
设置列表的长度,然后maplist(p(X1,...,Xn), List)
填充列表。或者,使用findall/3
,您可以执行findall(X, (between(1,N,_), p(X1,...,Xn,X)), L).
。
<小时/> 编辑根据问题的更新条件,生成的列表为唯一值...
random
谓词不是生成器,因此它们不会在回溯时创建新的随机数(无论是唯一的还是其他的)。因此,这个解决方案同样会生成一个满足要求的列表,然后成功而不会在回溯中产生更多这样的列表:
% Generate a random number X between A and B which is not in L
rand_not_in(A, B, L, X) :-
random(A, B, X1),
( memberchk(X1, L)
-> rand_not_in(A, B, L, X)
; X = X1
).
% Generate a list L of length N consisting of unique random numbers
% between A and B
random_list(N, L) :-
random_list(N, 50, 100, [], L).
random_list(N, A, B, Acc, L) :-
N > 0,
rand_not_in(A, B, A, X),
N1 is N - 1,
random_list(N1, A, B, [X|A], L).
random_list(0, _, _, L, L).
另一种方法,在SWI Prolog中,您可以使用randseq
,它会在1
到N
的范围内提供随机序列。只需缩放它:
random_list(N, A, B, L) :-
A < B,
Count is B - A + 1,
randseq(N, Count, L1),
Offset is A - 1,
maplist(offset(Offset), L1, L).
offset(X, Offset, Y) :-
Y is X + Offset.
?- random_list(5, 50, 100, L).
L = [54, 91, 90, 78, 75].
?-
答案 1 :(得分:1)
我发现这个小应用程序&#39; clpfd有趣:
?- N=10,M=12, repeat, findall(X, (between(1,N,_),random(1,M,X)), L), clpfd:all_different(L).
N = 10,
M = 12,
L = [5, 4, 6, 7, 9, 11, 2, 3, 8|...]
.
注意:M 必须是&gt; Ñ
答案 2 :(得分:1)
我想一个简单的方法是制作一个1:100的列表,并从中抽取100次大小为2的样本,无需替换。由于这是Prolog而不是R,你可以改为:
:- use_module(library(lists)).
:- use_module(library(random)).
random_pairs(Pairs) :-
findall(X/Y,
( between(1, 100, _),
randseq(2, 100, [X,Y])
), R).
这至少在SWI-Prolog中可用,但它是免费软件,网站上提供了randseq/3
的来源。
除非严格必要,否则最好不要使用findall
,最好写一下:
random_pairs(Pairs) :-
length(Pairs, 100),
maplist(randseq(2, 100), Pairs).
或者,如果X/Y
很重要,
random_pairs(Pairs) :-
length(Pairs, 100),
maplist(rand_couple(100), Pairs).
rand_couple(N, X/Y) :-
randseq(2, N, [X,Y]).
TL; DR 使用可用的库
答案 3 :(得分:0)
random_len([],0).
random_len([Q|T],N) :-
random(1,100,Q),
random_len(T,X),
N is X+1.