2011-11-09 29 views
0

こんにちは、指定したchar配列の繰り返しですべての組み合わせを取得しようとしています。 文字配列はアルファベット文字(下位のみ)で構成されており、長さが30文字以上の文字列を生成する必要があります。C#大きな文字セットの繰り返しでのChar置換文字列

私は多くのfor-loopのメソッドを試しましたが、文字列の長さがchar配列のcharのすべての組み合わせを5つ以上取得しようとすると、メモリ例外が発生します。

私は、最初の200000文字列、次に2000000文字しか取らない同様のメソッドを作成しました。これは、実績のあるものではあるが、長さの短い文字列でしか検証されませんでした。どんなそこの方法でそう前述したと私は私が30のlenghtsと文字列になるだろうforループ30を追加しようとしましたが、アプリケーションがちょうどhangs.Is

public static int Progress = 0; 
public static ArrayList CreateRngUrl7() 
     { 

      ArrayList AllCombos = new ArrayList(); 
      int passed = 0; 
      int Too = Progress + 200000; 

      char[] alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToLower().ToCharArray(); 

      for (int i = 0; i < alpha.Length; i++) 
       for (int i1 = 0; i1 < alpha.Length; i1++) 
        for (int i2 = 0; i2 < alpha.Length; i2++) 
         for (int i3 = 0; i3 < alpha.Length; i3++) 
          for (int i4 = 0; i4 < alpha.Length; i4++) 
           for (int i5 = 0; i5 < alpha.Length; i5++) 
            for (int i6 = 0; i6 < alpha.Length; i6++) 
           { 
            if (passed > (Too - 200000) && passed < Too) 
            { 
             string word = new string(new char[] { alpha[i], alpha[i1], alpha[i2], alpha[i3], alpha[i4], alpha[i5],alpha[i6] }); 
             AllCombos.Add(word); 
            } 

            passed++; 
           } 
      if (Too >= passed) 
      { 
       MessageBox.Show("All combinations of RNG7 were returned"); 
      } 
      Progress = Too; 
      return AllCombos; 
     } 

これは、7文字の長さと私の方法でしたこれを行うより良い方法は?すべての答えが高く評価されるだろう。前もって感謝します!

もっと大きな脚の文字列でどのように処理されているかを誰かに教えてください。ちょうど例を見たいですか?私はそのデータを格納する必要はありません、私はそれを何かと比較し、メモリから解放する必要があります。私はアルファベットを使用しました。たとえば、アルファベット全体を必要としませんでした。時間はかかりませんでしたか、どのくらいの組み合わせがありますか!!!!!

+1

char配列のすべての組み合わせの長さが30を超えるようにしたいですか?がんばろう!あなたはすぐにいつでもそれを必要としますか? – AndrewC

+0

私は多数のコンピュータにアクセスできます。私は方法例が必要です。 – formatc

+0

最後に30文字の文字列があり、長さがそれぞれ30であることに気づきます。これは1.6 * 10^34バイトです。あなたがグーグルでない限り、それを保存することはできません。 –

答えて

2

ループ内で文字列を割り当ててArrayListに格納するため、OutOfMemoryExceptionが返されます。文字列は、ArrayListがガベージコレクトされ、ループが格納できるよりも多くの文字列を作成するまで、メモリ内に留まる必要があります。

あなたは単にあなたがループ内でチェックを入れなければならない条件の文字列をチェックしたい場合:

for (... some crazy loop ...) { 
    var word = ... create word ... 
    if (!WordPassesTest(word)) { 
    Console.WriteLine(word + " failed test."); 
    return false; 
    } 
} 
return true; 

次に、あなたは、単一の単語のためのストレージを必要としています。もちろん、ループが十分にクレイジーであれば、宇宙の終わりより前に終了することはありません。

ネストされているが類似したループを多く実行する必要がある場合は、再帰を使用してコードを単純化することができます。 GenerateStrings(3)を呼び出す

Char[] chars = "ABCD".ToCharArray(); 

IEnumerable<String> GenerateStrings(Int32 length) { 
    if (length == 0) { 
    yield return String.Empty; 
    yield break; 
    } 
    var strings = chars.SelectMany(c => GenerateStrings(length - 1), (c, s) => c + s); 
    foreach (var str in strings) 
    yield return str; 
} 

は、遅延評価を使って長さ3のすべての文字列を生成します(ので、追加ストレージが文字列のために必要とされない):ここでは効率的で信じられないほどではありませんが、少なくともそれはシンプルで例があります。

文字列を生成する上に構築すると、文字列のバッファをバッファして処理するプリミティブを作成できます。簡単な解決策はReactive Extensions for .NETを使用することです。ここでは、すでにBufferプリミティブいる:Subscribe

GenerateStrings(3) 
    .ToObservable() 
    .Buffer(10) 
    .Subscribe(list => ... ship the list to another computer and process it ...); 

ラムダは最大10の文字列(Bufferへの呼び出しで提供パラメータ)でList<String>で呼び出されます。

コンピュータの数が限られていない限り、コンピュータをプールからプルして、計算が終了したらプールに戻すだけで済みます。

この質問のコメントから、あなたが自由に複数のコンピュータを持っていても26^30文字列を処理できないことは明らかです。

+0

これは私の計画でしたが、Imを複数のPCで実行する場合は、各PCとApplicationの各スレッドにいくつかの制限を設定する必要があります。 1.PC - 1スレッドは0-2000000を比較します。 var 2.PC - 2スレッドは2000000-4000000を同じvarに保存します 新しいスレッドが開始されると、最初の4000000行がチェックされており、4000000レコードから開始することがわかります。スレッドがいっぱいになった後、別のPCが次のレコードを取得できるように、進捗状況をネットワークまたはSQL Dbにファイルに保存します。 – formatc

+0

すばらしい例ありがとう!もう1つの質問はTakeを使って配列に文字列を入れ、メソッドをわずかに変更したり、条件が一致すれば正しいものだけを返すようにしてください。 スレッドに関する私の最初のコメントに対する解決策はありますか? – formatc

+0

@ user1010609:ネストされたループを書きたくない場合は再帰を使用してください。遅延評価を使うには 'IEnumerable'を使います。 'Buffer'のようなプリミティブを使用して、作業負荷を管理可能な部分に分割します。 –

-1

私はいくつかのコードを書く時間がありませんが、本質的にあなたはRAMを使い果たしているディスクを使用しています。私はアルゴリズムを実行している組み合わせを見つけ出すスレッドと、結果をディスクに保存してRAMを解放するスレッドを考えています。

+0

私はこのデータを保存する必要はありません。私はすでに持っている文字列と比較する必要があります。それは停止する必要があります一致します。実際の問題はRAMメモリではありません。問題は最初に100000文字列を生成し、それをスレッドに送信してチェックを行い、Loopが100000で停止したことを記憶しているので、次回100000-200000から生成します。そうすれば、複数のPC(ネットワーク上のProgress上のデータを格納できるように、別のPCを最初に停止した場所などで継続できるように)で実行できるようになります。私が上に投稿した方法は理想的ですが、私はループのためにあまりにも多くのものがあると思います。 – formatc

+0

既に述べたように、26^30の組み合わせが可能です。文字列あたり30文字で、必要な記憶域は84,395,967,038,542,377,577,758,630,888,479,145,622,241,280バイトです。 2TBハードディスクドライブは約39,299,934,654,749,174,405,708,271,492,495,735です。次の579,104,618,380,059,529,405年間の米国のGDPは、2TBドライブあたり220ドル(最高の価格/私が見つけることができるGB)です。 –

+0

うわー!私は実際にどのくらいのデータが生成されるかについて実際に考えることを止めませんでした。別の解決策が必要であると言うのは公正です。あなたが各組み合わせのハッシュでハッシュをチェックしてパスワードを解読しようとしていない限り、私はこの時点で賢明なことを言うのに十分な要件を理解していませんか? –

関連する問題