2013-11-03 5 views
5

私の悪い英語の私の言い訳の私。 私はstrからそれらを取るシンボルの組み合わせを生成しようとしています:TStringList(Xn、Yn)ここでXは新しい単語のcharの位置であり、Yはその位置の変数です。例えば
が、私は216個の言葉をexpactます私のSTRINGLISTはこの場合
X、Yの文字列は大量に入っています

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


を持って言うことができます(長さ(文字列[0])*長さ(文字列[1])*長さ(のstr [それまでは

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

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 

など:2]))結果は次のようになり

今、私はどのようにすべての可能な単語のためのciclesを作るために "ループ"を作るのに慣れています。一緒に

ループの巣3から

敬具あなたが持っているマーティン

+1

を、あなたは(コンパイル時に)言葉は、事前にご 'str'文字列リストに数える知っているのだろうか? – TLama

+0

いいえ、実行時にstrの数と各strの長さがロードされます。 – user2949632

+3

宿題のような音ですか? :) –

答えて

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; 
+0

hm私は理由を知っていますが、 "オペレータはこのoperendタイプには適用できません"というエラーのため、 "forList in start [startIx]"ではchを使用できません。多分古いバージョンのDelphiですか? (現在7) – user2949632

+0

@ user2949632、Delphi-7で動作するソリューションを追加しました。 –

+0

ありがとうございました。今度は、1mの組み合わせで2つの方法をテストして、「世代」の速度の違いを確認します。 – user2949632

1

が。

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; 

の代わりに:

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; 

あなたは文字長の可変数が必要な場合はこのようにそれを実現することができます。私は、strの配列のインデックスは1からゼロからスタートするが、二次元開始の指標と仮定しますi,j,kのような文字インデックスの固定変数を使用すると、それらを配列indexに格納することができます。インデックスを増やすと、紙に2つの数字を追加するときのように機能します。追加しようとすると、考えを得るために

999 
+ 1 
---- 

を取得してください。

+2

文字列の数がnの場合はどうなりますか? –

+0

私の最後のスクリプトはあなたのものとちょうど同じです。しかし今はループ回数に制限されています。だから私の質問は、 'str.Count-1'に従って実行時にFORループを実行する方法です。例えば、異なる条件でstr.count 100(生成されたすべての単語に対して100文字)を持ちます。そして私の最初の投稿で私の爆発の申し訳ありません。 – user2949632

+0

i、j、kのような固定変数の代わりに配列にインデックスを格納すると、最大で2つのネストされたサイクルで問題を解決することができます – nio

関連する問題