如何在Pascal中生成彼此唯一的随机整数 [英] how would you generate random integers that are unique from each other in pascal

查看:100
本文介绍了如何在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. 将数字1到49放入一个数组.
  2. 在阵列上执行随机播放.
  3. 提取前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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆