如何在Pascal中生成彼此唯一的随机整数 [英] how would you generate random integers that are unique from each other in pascal
问题描述
我想制作一个帕斯卡程序,选择1到49之间的6个随机整数.每个数字都应该是唯一的,即您不能使用'8,22'22'32'37'43',因为'22'是重复.如何在Delphi中实现这一点.
I would like to make a program in pascal that chooses 6 random integers between 1 and 49. each number should be unique i.e. you cannot have '8,22'22'32'37'43' because the '22' is repeated.How could I Implement this is in Delphi.
通过使用以下代码,我可以在1-49之间获得6个随机数.
I can get 6 random numbers between 1 - 49 by using the following code.
for i := 1 to 6 do
begin
num[i] := random(49) + 1
end
{next};
推荐答案
我会这样:
- 将数字1到49放入一个数组.
- 在阵列上执行随机播放.
- 提取前6个元素.
这可能不是最有效的方法,但它易于实施,易于理解,并且最重要的是,易于推断采样方法的分布特性.
It's probably not the most efficient way, but it's easy to implement, easy to understand, and, most crucially, easy to reason about the distributional properties of your sampling method.
对于随机播放,请使用 Fisher-Yates 随机播放.我在通用方法中实现了这一点:
For the shuffle, use Fisher-Yates shuffle. I implement that like this, in a generic method:
procedure TRandomNumberGenerator.Permute<T>(var Values: array of T);
var
i, Count: Integer;
begin
Count := Length(Values);
for i := 0 to Count-2 do
TGeneric.Swap<T>(Values[i], Values[i + Uniform(Count-i)]);
end;
其中,Uniform(N)
是我的RNG的函数,该函数返回从0..N-1
上的均匀分布得出的值.您可以在代码中将其替换为Random
.然后TGeneric.Swap<T>
交换两个元素.
where Uniform(N)
is the function of my RNG that returns a value drawn from the uniform distribution over 0..N-1
. You could replace that with Random
in your code. And TGeneric.Swap<T>
swaps the two elements.
您可以对其进行修改,使其适用于整数数组,如下所示:
You could modify this to work on an array of integers like so:
procedure Swap(var lhs, rhs: Integer);
var
tmp: Integer;
begin
tmp := lhs;
lhs := rhs;
rhs := tmp;
end;
procedure Permute(var Values: array of Integer);
var
i, Count: Integer;
begin
Count := Length(Values);
for i := 0 to Count-2 do
Swap(Values[i], Values[i + Random(Count-i)]);
end;
当然,您只需要执行循环的前六次迭代,因此非常有效的版本如下:
Of course, you only need to perform the first six iterations of the loop, so a very efficient version would be like this:
function Choose(M, N: Integer): TArray<Integer>;
var
i: Integer;
Values: TArray<Integer>;
begin
Assert(M>0);
Assert(N>=M);
SetLength(Values, N);
for i := 0 to N-1 do
Values[i] := i+1;
for i := 0 to Min(M-1, N-2) do
Swap(Values[i], Values[i + Random(N-i)]);
Result := Copy(Values, 0, M);
end;
您会将此传递称为6和49:
You would call this passing 6 and 49:
Values := Choose(6, 49);
如果您是一个疯狂的表演狂,那么我认为很难克服这个问题:
If you were a mad performance freak then I think it would be hard to beat this:
type
TArr6 = array [0..5] of Integer;
PArr6 = ^TArr6;
TArr49 = array [0..48] of Integer;
const
OrderedArr49: TArr49 = (
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49
);
function Choose6: TArr6;
var
i: Integer;
Values: TArr49;
begin
Values := OrderedArr49;
for i := 0 to high(Result) do begin
Swap(Values[i], Values[i + Random(Length(Values)-i)]);
end;
Result := PArr6(@Values)^;
end;
我应该说,我怀疑性能是否会成为驱动因素.
I should say that I doubt that performance would be the driving factor here.
这篇关于如何在Pascal中生成彼此唯一的随机整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!