德尔福 - 随机组合(数学)

时间:2013-04-06 11:28:39

标签: delphi math random combinations

我这里有一个大问题,甚至不知道如何开始......

简而言之,我需要知道一个数字是否来自随机组合的一组结果...

让我更好地解释一下:我创建了一个随机“数字”,其中包含3个整数字符,从1到8,如下所示:

procedure TForm1.btn1Click(Sender: TObject);
var
  cTmp: Char;
  sTmp: String[3];
begin
  sTmp := '';
  While (Length(sTmp) < 3) Do
  Begin
    Randomize;
    cTmp := IntToStr(Random(7) + 1)[1];
    If (Pos(cTmp, sTmp) = 0) Then
      sTmp := sTmp + cTmp;
  end;
  edt1.Text := sTmp;
end;

现在我需要知道的是其他随机数,比如说“324”(例子),就是随机组合的结果集。

请有人可以帮忙吗?获得方程式来解决这个问题的链接就足够了......


好的,让我尝试添加一些有用的信息:

请首先查看此链接https://en.wikipedia.org/wiki/Combination

一旦我得到一个用户输入的数字,在编辑框中,我需要检查它是否在这个随机组合的集合中:S =(1..8)和k = 3

整蛊,哼哼?


这是我得到的。也许它对未来的人有用。感谢所有试图提供帮助的人!

Function IsNumOnSet(const Min, Max, Num: Integer): Boolean;
var
  X, Y, Z: Integer;
Begin
  Result := False;
  For X := Min to Max Do
    For Y := Min to Max Do
      For Z := Min to Max Do
        If (X <> Y) and (X <> Z) and (Y <> Z) Then
          If (X * 100 + Y * 10 + Z = Num) Then
          Begin
            Result := True;
            Exit;
          end;
end;

4 个答案:

答案 0 :(得分:1)

你有你的发电机。建立价值后,执行类似

的操作
function isValidCode( Digits : Array of Char;  Value : String ) : Boolean;
var 
    nI : Integer;
begin
       for nI := 0 to High(Digits) do
       begin
             result := Pos(Digits[nI], Value ) > 0;
             if not result then break;
       end;
end;

这样打电话......

 isValidCode(["3","2","4"], RandomValue);

注意:它的作用只是因为你有唯一的数字,数字3只有你最后的数字一次。对于更通用的东西,你必须调整这个功能。 (测试“3”,“3”,“2”将返回true但它将是错误的!)

更新 : 我不喜欢嵌套循环^^。这是一个返回整数的nTh数字的函数。如果数字不存在,它将返回-1。 :

 function TForm1.getDigits(value : integer; ndigits : Integer ) : Integer;
 var
    base : Integer;
 begin
       base := Round(IntPower( 10, ndigits-1 ));
       result := Trunc( value /  BASE ) mod 10;
 end;

nDigits是从1开始从右到左的数字。它将返回数字的值。

GetDigits( 234, 1) returns 4
GetDigits( 234, 2) returns 3
GetDigits( 234, 3) returns 2.
GetDigits( 234, 4) returns 0.

现在最后一个函数检查一个值是否是一个好的组合,指定你要查找的maxdigits:

function isValidCombination( value : integer; MinVal, MaxVal : Integer; MaxDigits : Integer ) :  Boolean;
var
   Buff : Array[0..9] of Integer;
   nI, digit: Integer;
 begin
   ZeroMemory( @Buff, 10*4);

   // Store the count of digits for
   for nI := 1 to MaxDigits do
   begin
      digit := getDigits(value, nI);
      Buff[digit] :=  Buff[digit] + 1;
   end;

   // Check if the value is more than the number of digits.
   if Value >= Round(IntPower( 10, MaxDigits )) then
   begin
     result := False;
     exit;
   end;

   // Check if the value has less than MaxDigits. 
   if Value < Round(IntPower( 10, MaxDigits-1 )) then
   begin
      result := False;
      exit;
   end;


  result := true;
  for nI := 0 to 9 do
  begin
     // Exit if more than One occurence of digit.
     result := Buff[nI] < 2 ;
     if not result then break;

     // Check if digit is present and valid.
     result := (Buff[nI] = 0) or InRange( nI, MinVal, MaxVal );
     if not result then break;
  end;

end;

答案 1 :(得分:1)

您想测试某些内容是否是一种组合。为此,您需要验证推定的组合是否满足以下条件:

  1. 每个元素的范围都是1..N和
  2. 没有元素出现过多次。
  3. 所以,像这样实现它。

    • 声明一个计数数组,比如整数的数组[1..N]。如果N在运行时变化,则需要动态数组。
    • 将数组的所有成员初始化为零。
    • 遍历推定组合的每个元素。检查元素是否在1..N范围内。并增加该元素的计数。
    • 如果任何元素的计数大于1,则这不是有效组合。

    现在你可以通过用一组布尔值替换整数数组来简化,但这应该是不言而喻的。

答案 2 :(得分:0)

问题对我来说似乎不太模糊, 也许说得不好。

根据我的理解,你想检查一个字符串是否在一组随机生成的字符中。

以下是最快的工作方式,保留所有字母的排序数组以及每个字母的次数。

从目标字符串中减去每个字母 如果sorted int数组中的任何值低于0,则表示无法从这些字符生成字符串。

我只使用不区分大小写的字符串,但通过使字母数组长度为255个字符而不是从A开始,可以很容易地使用任何字符串。

这将不允许您像其他示例一样使用两次字符 所以'繁荣'不在'b''o'''''

希望这会对你有所帮助。

function TForm1.isWordInArray(word: string; arr: array of Char):Boolean;
 var
   alphabetCount: array[0..25] of Integer;
   i, baseval, position : Integer;
   s: String;
   c: Char;
begin
  for i := 0  to 25 do alphabetCount[i] := 0;  // init alphabet
  s := UpperCase(word); // make string uppercase
  baseval := Ord('A'); // count A as the 0th letter
  for i := 0 to Length(arr)-1 do begin // disect array and build alhabet
    c := UpCase(arr[i]); // get current letter
    inc(alphabetCount[(Ord(c)-baseval)]); // add 1 to the letter count for that letter
  end;
  for i := 1 to Length(s) do begin // disect string
    c := s[i]; // get current letter
    position := (Ord(c)-baseval);
    if(alphabetCount[position]>0) then // if there is still latters of that kind left
      dec(alphabetCount[position]) // delete 1 to the letter count for that letter
    else begin // letternot there!, exit with a negative result
      Result := False;
      Exit;
    end;
  end;
  Result := True; // all tests where passed, the string is in the array
end;

如此实施:

if isWordInArray('Delphi',['d','l','e','P','i','h']) then Caption := 'Yup' else Caption := 'Nope';  //yup
if isWordInArray('boom',['b','o','m']) then Caption := 'Yup' else Caption := 'Nope';  //nope, a char can only be used once

德尔福摇滚!

答案 3 :(得分:-1)

begin
  Randomize; //only need to execute this once.
  sTmp := '';
  While (Length(sTmp) < 3) Do
  Begin
    cTmp := IntToStr(Random(7) + 1)[1]; // RANDOM(7) produces # from 0..6
                                        // so result will be '1'..'7', not '8'
                                        // Alternative: clmp := chr(48 + random(8));
    If (Pos(cTmp, sTmp) = 0) Then
      sTmp := sTmp + cTmp;
    IF SLMP = '324' THEN
      DOSOMETHING; // don't know what you actually want to do
                   // Perhaps SET SLMP=''; to make sure '324'
                   // isn't generated?
  end;
  edt1.Text := sTmp;
end;