Dynamic character generator; Generate all possible strings from a character set

╄→尐↘猪︶ㄣ 提交于 2019-12-11 13:52:58

问题


I want to make a dynamic string generator that will generate all possible unique strings from a character set with a dynamic length.

I can make this very easily using for loops but then its static and not dynamic length.

// 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)
        }
    }
}

But when I want to make this dynamic of length so I can just call generate(length: 5) I get confused.

I found this Stackoverflow question But the accepted answer generates strings 1-maxLength length and I want maxLength on ever string.


回答1:


As noted above, use recursion. Here is how it can be done with 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();

}

Please note that the run time of this algorithm and the amount of data it returns is exponential as the length increases which means that if you have large lengths, you should expect the code to take a long time and to return a huge amount of data.




回答2:


Translation of @YacoubMassad's C# code to Swift:

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"]))

Prints:

aaa, aab, aac, aba, abb, abc, aca, acb, acc, baa, bab, bac, bba, bbb, bbc, bca, bcb, bcc, caa, cab, cac, cba, cbb, cbc, cca, ccb, ccc




回答3:


While you can (obviously enough) use recursion to solve this problem, it quite an inefficient way to do the job.

What you're really doing is just counting. In your example, with "a", "b" and "c" as the allowed characters, you're counting in base 3, and since you're allowing three character strings, they're three digit numbers.

An N-digit number in base M can represent NM different possible values, going from 0 through NM-1. So, for your case, that's limit=pow(3, 3)-1;. To generate all those values, you just count from 0 through the limit, and convert each number to base M, using the specified characters as the "digits". For example, in C++ the code can look like this:

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

One minor note: as I've written it here, this produces the output in basically a little-endian format. That is, the "digit" that varies the fastest is on the left, and the one that changes the slowest is on the right.



来源:https://stackoverflow.com/questions/32719912/dynamic-character-generator-generate-all-possible-strings-from-a-character-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!