2011-11-09 27 views
0

你好我試圖讓所有可能的組合重複給定的字符數組。 字符數組由字母組成(只有更低),我需要生成長度爲30或更多字符的字符串。C#字符在一大組字符上的重複排列

我嘗試了很多for循環的方法,但是當我嘗試獲取char數組中字符長度超過5的所有char組合時,我得到了內存異常。

所以我創建了類似的方法,只需要第一個200000字符串,然後下一個2000000等等,這被證明成功,但只有較小的長度的字符串。

這是我的方法有7個字符長度:

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; 
     } 

我試着用上面,所以我將得到與30,但lenghts串所描述的方法添加30 for循環應用程序只是hangs.Is有什麼更好的方法來做到這一點?所有的答案將不勝感激。先謝謝你!

有人可以請只是發佈方法它如何處理更大的legth字符串我只是想看到一個例子?我不必存儲這些數據,我只需要將其與某些內容進行比較並從內存中釋放它。我用字母表例如我不需要整個字母表。問題不是需要多長時間或多少組合纔會是!

+1

你想要每個長度超過30的char數組組合嗎?祝你好運!你很快就需要它嗎? – AndrewC

+0

我可以訪問大量的計算機。我只需要一個示例方法。 – formatc

+0

你的確意識到它最終會是'30!'不同的字符串,每個長度都是30 * 1.6 * 10^34字節。除非你是谷歌,否則你不能存儲(如果他們可以的話) –

回答

2

你得到一個OutOfMemoryException,因爲在循環中你分配一個字符串並將它存儲在一個ArrayList。字符串必須留在內存中,直到ArrayList被垃圾收集爲止,並且您的循環會創建比您能夠存儲的字符串更多的字符串。

如果你只是想檢查條件的字符串,你應該把檢查內循環:

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

然後你只需要存儲的一個字。當然,如果循環足夠瘋狂,它不會在我們所知的宇宙結束之前終止。

如果您需要執行許多嵌套但類似的循環,您可以使用遞歸來簡化代碼。這裏要說的是不令人難以置信有效的例子,但至少它很簡單:

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; 
} 

調用GenerateStrings(3)將產生使用惰性計算(因此沒有額外的存儲空間是必需的字符串)長度爲3的所有字符串。

基於IEnumerable生成字符串,您可以創建初始值來緩衝和處理字符串緩衝區。一個簡單的解決方案是使用.NET的Reactive Extensions。在這裏,你已經有一個Buffer原始:

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

Subscribe拉姆達將與List<String>被稱爲至多10串(在調用提供給Buffer參數)。

除非您擁有無限數量的計算機,否則您將不得不從計算池中提取計算機,並且只有在計算完成後纔將其回收到池中。

從這個問題的評論中可以明顯看出,即使您有多臺電腦,您也無法處理26^30個字符串。

+0

這是我的計劃,但如果我要在多臺PC上執行它,我必須爲每臺PC和每個應用程序的線程設置一些限制。例如: 1.PC-1線程比較0-2000000保存數量2000000 to var 2.PC-2線程比較2000000-4000000保存數字到相同的變量 所以當新的線程啓動時,它可以知道前4000000行正在檢查,它應該從4000000記錄開始。線程已滿後將進度保存到網絡或SQL Db上的文件,以便另一臺電腦可以接收下一個記錄等等。 – formatc

+0

很好的例子謝謝!還有一個問題,我應該使用Take來放置數組中的字符串,然後比較或者應該稍微改變你的方法,並且如果條件是這樣,它只返回正確的匹配。 你有任何解決我的線程的第一個評論? – formatc

+0

@ user1010609:如果您不想編寫嵌套循環,請使用遞歸。使用'IEnumerable'來使用懶惰評估。使用像「緩衝區」這樣的基元將您的工作負載切割成可管理的部分。 –

-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個字節的存儲空間。其中約39,299,934,654,749,174,405,708,271,492,495,735 2TB硬盤。每2TB驅動器220美元(最佳價格/ GB我可以找到),這是美國未來579,104,618,380,059,529,405年的國內生產總值... –

+0

哇!我並沒有停下來想想會產生多少數據。可以公平地說,需要另一種解決方案。我不明白這個要求足以說明在這一點上有什麼明智之處,除非你試圖通過檢查每個組合的哈希散列來破解密碼? –