Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a good way for figuring out all possible words of a given length

I'm trying to create an algorithm in C# which produces the following output strings:

AAAA
AAAB
AAAC
...and so on...
ZZZX
ZZZY
ZZZZ

What is the best way to accomplish this?

public static IEnumerable<string> GetWords()
{
    //Perform algorithm
    yield return word;
}
like image 616
Frode Lillerud Avatar asked Nov 23 '08 17:11

Frode Lillerud


5 Answers

well, if the length is a constant 4, then this would handle it:

public static IEnumerable<String> GetWords()
{
    for (Char c1 = 'A'; c1 <= 'Z'; c1++)
    {
        for (Char c2 = 'A'; c2 <= 'Z'; c2++)
        {
            for (Char c3 = 'A'; c3 <= 'Z'; c3++)
            {
                for (Char c4 = 'A'; c4 <= 'Z'; c4++)
                {
                    yield return "" + c1 + c2 + c3 + c4;
                }
            }
        }
    }
}

if the length is a parameter, this recursive solution would handle it:

public static IEnumerable<String> GetWords(Int32 length)
{
    if (length <= 0)
        yield break;

    for (Char c = 'A'; c <= 'Z'; c++)
    {
        if (length > 1)
        {
            foreach (String restWord in GetWords(length - 1))
                yield return c + restWord;
        }
        else
            yield return "" + c;
    }
}
like image 193
Lasse V. Karlsen Avatar answered Oct 17 '22 03:10

Lasse V. Karlsen


There's always the obligatory LINQ implementation. Most likely rubbish performance, but since when did performance get in the way of using cool new features?

var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();

var sequence = from one in letters
               from two in letters
               from three in letters
               from four in letters
               orderby one, two, three, four
               select new string(new[] { one, two, three, four });

'sequence' will now be an IQueryable that contains AAAA to ZZZZ.

Edit:

Ok, so it was bugging me that it should be possible to make a sequence of configurable length with a configurable alphabet using LINQ. So here it is. Again, completely pointless but it was bugging me.

public void Nonsense()
{
    var letters = new[]{"A","B","C","D","E","F",
                        "G","H","I","J","K","L",
                        "M","N","O","P","Q","R","S",
                        "T","U","V","W","X","Y","Z"};

    foreach (var val in Sequence(letters, 4))
        Console.WriteLine(val);
}

private IQueryable<string> Sequence(string[] alphabet, int size)
{
    // create the first level
    var sequence = alphabet.AsQueryable();

    // add each subsequent level
    for (var i = 1; i < size; i++)
        sequence = AddLevel(sequence, alphabet);

    return from value in sequence
           orderby value
           select value;
}

private IQueryable<string> AddLevel(IQueryable<string> current, string[] characters)
{
    return from one in current
           from character in characters
           select one + character;
}

The call to the Sequence method produces the same AAAA to ZZZZ list as before but now you can change the dictionary used and how long the produced words will be.

like image 37
Garry Shutler Avatar answered Oct 17 '22 02:10

Garry Shutler


Just a coment to Garry Shutler, but I want code coloring:

You really don't need to make it IQuaryable, neither the sort, so you can remove the second method. One step forwad is to use Aggregate for the cross product, it end up like this:

IEnumerable<string> letters = new[]{
                "A","B","C","D","E","F",                       
                "G","H","I","J","K","L",
                "M","N","O","P","Q","R","S",           
                "T","U","V","W","X","Y","Z"};

var result = Enumerable.Range(0, 4)
                .Aggregate(letters, (curr, i) => curr.SelectMany(s => letters, (s, c) => s + c));

foreach (var val in result)
     Console.WriteLine(val);

Anders should get a Nobel prize for the Linq thing!

like image 44
Olmo Avatar answered Oct 17 '22 04:10

Olmo


GNU Bash!

{a..z}{a..z}{a..z}{a..z}
like image 21
Johannes Schaub - litb Avatar answered Oct 17 '22 04:10

Johannes Schaub - litb


Python!

(This is only a hack, dont' take me too seriously :-)

# Convert a number to the base 26 using [A-Z] as the cyphers
def itoa26(n): 
   array = [] 
   while n: 
      lowestDigit = n % 26
      array.append(chr(lowestDigit + ord('A'))) 
      n /= 26 
   array.reverse() 
   return ''.join(array)

def generateSequences(nChars):
   for n in xrange(26**nChars):
      string = itoa26(n)
      yield 'A'*(nChars - len(string)) + string

for string in generateSequences(3):
   print string
like image 1
Federico A. Ramponi Avatar answered Oct 17 '22 03:10

Federico A. Ramponi