5

Firs of all excuse me for my bad english. I'm trying to generate combinations of symbols taking them from str: TStringList (Xn, Yn) where X is the position of the char in the new word and Y is the variable for the position.
For example lets say my StringList have

str[0]: '013456789'          
str[1]: 'abcdef'
str[2]: '5421'


In this case I will expact 216 words (length(str[0]) * length(str[1]) * length(str[2])) The result will be like:

str[0][1]+ str[1][1]+ str[2][1] -> 0a5
str[0][1]+ str[1][1]+ str[2][2] -> 0a4
str[0][1]+ str[1][1]+ str[2][3] -> 0a2
str[0][1]+ str[1][1]+ str[2][4] -> 0a1

str[0][1]+ str[1][2]+ str[2][1] -> 0b5
str[0][1]+ str[1][2]+ str[2][2] -> 0b4
str[0][1]+ str[1][2]+ str[2][3] -> 0b2
str[0][1]+ str[1][2]+ str[2][4] -> 0b1

str[0][1]+ str[1][3]+ str[2][1] -> 0c5
str[0][1]+ str[1][3]+ str[2][2] -> 0c4
str[0][1]+ str[1][3]+ str[2][3] -> 0c2
str[0][1]+ str[1][3]+ str[2][4] -> 0c1

and so on untill

str[0][10]+ str[1][6]+ str[2][3] -> 9f2 
str[0][10]+ str[1][6]+ str[2][4] -> 9f1

Now I'm comfused how to make the "FOR" loops to make cicles for every possible word.

Best regards Martin

4

2 回答 2

3

这可以通过递归来完成。

procedure Recurse(startIx,stopIx: Integer; prefix: String; const aList: TStringList);
var
  ch : Char;
begin
  if (startIx > stopIx) then begin
    WriteLn(prefix);
  end
  else
  begin
    for ch in aList[startIx] do begin
      Recurse( startIx+1,stopIx,prefix + ch,aList);
    end;
  end;
end;

Recurse(0,str.Count-1,'',str);

递归乍一看似乎很神奇,但它是解决这种组合数学的一种非常有效的方法。

这个问题的解决方案是一个Cartesian product.

如果您有较旧的 Delphi 版本,请像这样迭代字符:

procedure Recurse(startIx,stopIx: Integer; prefix: String; const aList: TStringList);
var
  i : Integer;
begin
  if (startIx > stopIx) then begin
    WriteLn(prefix);
  end
  else
  begin
    for i := 1 to Length(aList[startIx]) do begin
      Recurse( startIx+1,stopIx,prefix + aList[startIx][i],aList);
    end;
  end;
end;
于 2013-11-03T14:19:12.443 回答
1

您必须将 3 个 for 循环嵌套在一起。我假设 str 数组的索引从零开始,但第二维的索引从 1 开始:

var i,j,k:integer;

begin
    s = '';
    for i:=1 to length(str[0]) do
        for j:=1 to length(str[1]) do
            for k:=1 to length(str[2]) do
            begin
                combination := str[0][i]+str[1][j]+str[2][k];
                s := s + combination + chr(13) + chr(10);
            end;
    { you have all combinations in string s }
end;

如果您需要可变数量的字符长度,您可以像这样实现它:

procedure TForm1.FormCreate(Sender: TObject);
var str: array [0..10] of string;
    lengths : array [0..10] of integer;
    combination : string;
    index: array [0..10] of integer;
    n, i,j : integer;
    maxn : integer;
begin
    n := 3; { actual number of charaters in output word }
    str[0]:= '013456789';
    str[1]:= 'abcdef';
    str[2]:= '5421';


    { lengths will be used often later so they will be determined one time }
    for i:=0 to n-1 do lengths[i] := length(str[i]);
    maxn := 1; { maxn will be used to determine how meny iterations to make }
    for i:=0 to n-1 do maxn := maxn * lengths[i];
    { start at index 1 (first character) with each character position }
    for i:=0 to n-1 do index[i]:=1;


    memo1.Lines.Add(inttostr(maxn));

    { iterate all possibilities }
    for i:=1 to maxn do
    begin
      { start creating a combination }
      combination:='';
      for j:=0 to n-1 do
      begin
        combination := combination + str[j][index[j]];
      end;
      memo1.Lines.Add(combination);
      { increment indexes, from last to the first }
      for j:=n-1 downto 0 do
      begin
        index[j] := index[j]+1;
        { if index is in bounds of character posibilities stop incremented indexes,
          otherwise reset the index and increment next one }
        if index[j]<=lengths[j] then
        begin
            break; { stop incrementing indexes }
        end else begin
            index[j] := 1; { reset the index }
            { the loop will continue incrementing previous index }
        end;
      end;
    end;
end;

而不是使用固定变量作为字符索引,i,j,k您可以将它们存储在数组index中。索引的递增就像您在纸上手动添加两个数字一样。尝试添加

 999
+  1
----

得到这个想法。

于 2013-11-03T12:34:33.713 回答