2015-09-22 66 views
1

我想創建一個動態字符串生成器,它將從具有動態長度的字符集中生成所有可能的唯一字符串。動態字符發生器;從字符集生成所有可能的字符串

我可以很容易地使用for循環,但然後它的靜態和動態長度。

// Prints all possible strings with the length of 3 

for a in allowedCharacters { 
    for b in allowedCharacters { 
     for c in allowedCharacters { 
      println(a+b+c) 
     } 
    } 
} 

但是,當我想讓長度的這個充滿活力的,所以我可以叫我generate(length: 5)感到困惑。

我找到了這個Stackoverflow question但接受的答案生成字符串1-maxLength長度,我希望maxLength永遠字符串。

+1

爲什麼不使用遞歸? – Dmitry

+2

@Arbitur確保解釋「製作重複並且沒有排序」是指 - 在您的文章中沒有提及任何限制,但您聲稱鏈接的解決方案是不可接受的... –

+0

@AlexeiLevenkov鏈接的答案產生了一些像這樣:a,b,aa,aa,ab,bb,bb,ab。幾個重複。 – Arbitur

回答

4

如上所述,使用遞歸。下面是它如何能夠用C#來完成:

static IEnumerable<string> Generate(int length, char[] allowed_chars) 
{ 
    if (length == 1) 
    { 
     foreach (char c in allowed_chars) 
      yield return c.ToString(); 
    } 
    else 
    { 
     var sub_strings = Generate(length - 1, allowed_chars); 

     foreach (char c in allowed_chars) 
     { 
      foreach (string sub in sub_strings) 
      { 
       yield return c + sub; 
      } 

     } 
    } 
} 

private static void Main(string[] args) 
{ 

    string chars = "abc"; 

    List<string> result = Generate(3, chars.ToCharArray()).ToList(); 

} 

請注意,這種算法並返回數據量的運行時間是指數隨着長度的增加,這意味着,如果你有大的長度,你應該期望代碼花費很長時間並返回大量數據。

+0

我會把它翻譯成Swift和Ill return :) – Arbitur

+0

這個看起來和鏈接文章中提出的解決方案基本相同。請確保澄清它是如何不同(忽略迭代器部分)。它也沒有解決這樣一個事實,即相關的建議「重複並且沒有命令」(不管它是什麼意思)。 –

+0

引用的問題需要所有長度達特定長度的字符串,但這個問題需要所有特定長度的字符串。另一個問題的答案是將結果直接寫入控制檯,在這裏我們生成數據並將它們返回給調用者。 –

1

翻譯@ YacoubMassad的C#代碼斯威夫特:

func generate(length: Int, allowedChars: [String]) -> [String] { 
    if length == 1 { 
     return allowedChars 
    } 
    else { 
     let subStrings = generate(length - 1, allowedChars: allowedChars) 

     var arr = [String]() 
     for c in allowedChars { 
      for sub in subStrings { 
       arr.append(c + sub) 
      } 
     } 

     return arr 
    } 
} 

println(generate(3, allowedChars: ["a", "b", "c"])) 

打印:

AAA,AAB,AAC,ABA,ABB,美國廣播公司,ACA,ACB,ACC,咩,BAB, BAC,BBA,BBB,BBC,BCA,BCB,BCC,CAA,CAB,CAC,CBA,CBB,CBC,CCA,CCB,CCC

+0

如果您對代碼的評論(例如可能的改進)感興趣,那麼您可以在http://codereview.stackexchange.com/tour上發佈它。 –

+0

謝謝@MartinR我還沒有探討其他堆棧交換論壇:) – Arbitur

1

雖然你可以(顯然不夠)使用遞歸來解決Ť他的問題,這是做這項工作的一種低效率的方式。

你真的在做什麼只是計數。在你的例子中,使用「a」,「b」和「c」作爲允許的字符,你要計算基數3,並且由於你允許三個字符串,所以它們是三位數字。

基數M中的N位數可以表示從0到NM -1的不同可能值。所以,對於你的情況,這是limit=pow(3, 3)-1;。要生成所有這些值,只需從0到極限值進行計數,然後將每個數字轉換爲基數M,並使用指定的字符作爲「數字」。例如,在C++代碼可以是這樣的:

#include <string> 
#include <iostream> 

int main() { 
    std::string letters = "abc"; 
    std::size_t base = letters.length(); 
    std::size_t digits = 3; 

    int limit = pow(base, digits); 

    for (int i = 0; i < limit; i++) { 
     int in = i; 
     for (int j = 0; j < digits; j++) { 
      std::cout << letters[in%base]; 
      in /= base; 
     } 
     std::cout << "\t"; 
    } 
} 

一個小小的提示:我在這裏寫它,這將產生輸出基本上是小端格式。也就是說,變化最快的「數字」在左邊,而變化最慢的那個在右邊。