1

如何在 Delphi (Object Pascal) 中实现以下算法:

  • 每个字母数字项将是一个对象(在我的情况下是对文件字符串的引用)。
  • 可以枚举(输出)每个拾取状态/组合。
  • 想象算盘的柱子;都具有相同的大小(根据其基础)。我需要不同大小的列。(在我的情况下,不同大小的文件字符串集)

最后编辑:请参阅Python intertools implementation

其他语言中的类似算法:c#rubyjavaphp

算法

考虑以下集合及其成员:

S1 = {a1, a2, a3, a4, a5}

S2 = {b1, b2, b3, b4}

S3 = {c1, c2, c3, c4, c5}

选择每组的第一个成员(P = Pick States):

P1 = {a1, b1, c1}

然后,增加第一个直到它的极限:

P2 = {a2, b1, c1} P3 = {a3, b1, c1} P4 = {a4, b1, c1} P5 = {a5, b1, c1}

然后,重置第一个集合,并增加第二个集合的“一个”;

P6 = {a1, b2, c1}

再次增加第一组……依此类推……为第三组上的每个“加一”重置第一组和第二组。

P7 = {a2, b2, c1}

关于计数的基本原理或乘法原理,该算法将生成 100 个选择状态/组合。

P100 = {a5, b4, c5}

4

2 回答 2

1

我已经使用递归和条件调用达成了解决方案。我用这种结构创建了一条记录:

  TGridKey = record
    ID : Integer;
    Index : Integer;
    Files : TStringList;
  end;

  TTrialSet = record
    theGrid : array of TGridKey;
  end;

在 TForm 类中使用此名称。

TfRandStimuliSet = class (TForm)

    //...
    lst1: TListBox; 
    dlgOpenPic: TOpenPictureDialog;
private        
    FTrialSet: TTrialSet;
    procedure TfRandStimuliSet.SubSetsMountEngine;
    //...
end;

设置网格数组的长度:

  NumComp := 3;
  SetLength(FTrialSet.theGrid, NumComp);
  for I := Low(FTrialSet.theGrid) to High(FTrialSet.theGrid) do
  begin
    FTrialSet.theGrid[I].ID := I;
    FTrialSet.theGrid[I].Index:= -1;
    FTrialSet.theGrid[I].Files := TStringList.Create;
  end;

在每个“I”网格中放置一些字符串:

if dlgOpenPic.Execute then
  begin
    if dlgOpenPic.Files.Count > 0 then
    for K := 0 to (dlgOpenPic.Files.Count - 1) do
    begin
     FTrialSet.theGrid[I].Files.Add(dlgOpenPic.Files.Strings[K]);
    end;
    dlgOpenPic.Files.Clear;
  end;

然后程序:

procedure TfRandStimuliSet.SubSetsMountEngine;
var ID: integer; s1 : string;
  procedure AddStmFromGrid(Grid, Stm : Integer);
  begin
    s1 := s1 + ExtractFileName(FTrialSet.theGrid[Grid].Files.Strings[Stm]) + ',';
  end;

  procedure AddTrialFromIndex; //each trial is the current index's
  var I: Integer;
  begin

    for I:= Low(FTrialSet.theGrid) to High(FTrialSet.theGrid) do
      AddStmFromGrid(I,FTrialSet.theGrid[I].Index);
    lst1.Items.Add(s1);
    s1:= '';
  end;

  procedure IndexReset(aGrid : Integer);
  var i : Integer;
  begin
    for  I := aGrid to (High(FTrialSet.theGrid)) do
      FTrialSet.theGrid[I].Index := 0
  end;

  procedure IndexInc(aGrid : Integer);
  begin
    AddTrialFromIndex; //Save
    Inc(FTrialSet.theGrid[aGrid].Index);
  end;

      function MoveGrid(var ID:integer): Boolean;   //begin from right most, the highest grid
      var IDMaxIndex, IDCurIndex, LowID, HighID: Integer;
      begin
        Result := True;
        LowID := Low(FTrialSet.theGrid);
        HighID := High(FTrialSet.theGrid);
        //Application.ProcessMessages;
        if  (ID < LowID) then 
          begin
            //ShowMessage('False');
            AddTrialFromIndex;
            Result := False;
          end
        else
          begin
            IDMaxIndex:= FTrialSet.theGrid[ID].Files.Count -1;
            IDCurIndex := FTrialSet.theGrid[ID].Index;

            if IDCurIndex = IDMaxIndex then  
              begin
                ID := ID - 1;
                Result:= MoveGrid(ID);//moveleft
                Exit;
              end;
            if   (ID < HighID)
             and (IDCurIndex < IDMaxIndex) then 
              begin
                IndexInc(ID);                 //increment/move donw
                IndexReset(ID + 1);           //reset everything on the right
                MoveGrid(HighID);             //move to the most right/next down
                Exit;
              end;
            if  (ID = (HighID))
             and (IDCurIndex < IDMaxIndex) then
              begin
                IndexInc(ID);          //increment/move down 
                MoveGrid(ID)           //next increment/move down
              end;  
          end;
      end;
begin
  ID := High(FTrialSet.theGrid);
  IndexReset(Low(FTrialSet.theGrid));  //0's for everyone
  MoveGrid(ID); //begin from the most right
end;
于 2013-04-12T04:11:32.203 回答
1

你在数。

每个珠子都是一个数字,在您的示例中,您正在以 5 为基数工作,因为每个珠子可以有 5 个位置之一。

要确定珠子的哪个位置对应于给定的整数,只需将该整数写入相关的基数就足够了。以下是在 ruby​​ 中的操作方法17

>> 17.to_s(5).rjust(3, '0')
=> "032"

在这里,我左填充了 3 个珠子以清楚每个珠子的位置,并且我使用的约定是珠子从位置 0 开始,而不是位置 1。

于 2013-04-10T06:20:35.667 回答