Какой хороший способ выяснить все возможные слова заданной длины

Я пытаюсь создать алгоритм в С#, который создает следующие выходные строки:

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

Каков наилучший способ для этого?

public static IEnumerable<string> GetWords()
{
    //Perform algorithm
    yield return word;
}

Ответ 1

Хорошо, если длина является константой 4, то это будет обрабатывать ее:

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

если длина является параметром, это рекурсивное решение будет обрабатывать:

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

Ответ 2

Всегда есть обязательная реализация LINQ. Скорее всего, производительность мусора, но с каких пор производительность способствовала использованию новых интересных функций?

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' теперь будет IQueryable, который содержит AAAA для ZZZZ.

Edit:

Хорошо, поэтому мне было сложно, что можно сделать последовательность настраиваемой длины с настраиваемым алфавитом с помощью LINQ. Так вот оно. Опять же, совершенно бессмысленно, но это подслушивало меня.

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

Вызов метода Sequence приводит к тому же списку AAAA в ZZZZ, как и раньше, но теперь вы можете изменить используемый словарь и как долго будут выполняться произносимые слова.

Ответ 3

Как раз для Гарри Шатлера, но мне нужна окраска кода:

Вам действительно не нужно делать это IQuaryable, ни сортировка, поэтому вы можете удалить второй метод. Один шаг forwad - использовать Aggregate для кросс-продукта, он заканчивается следующим образом:

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

Андерс должен получить Нобелевскую премию за предмет Линку!

Ответ 4

GNU Bash!

{a..z}{a..z}{a..z}{a..z}

Ответ 5

Вдохновленный ответом Garry Shutler, я решил перекодировать его ответ в T-SQL.

Скажем, что "Письма" - это таблица с одним полем, MyChar, a CHAR (1). Он имеет 26 строк, каждая - буква алфавита. Таким образом, у нас есть (вы можете скопировать-вставить этот код на SQL Server и запустить как есть, чтобы увидеть его в действии):

DECLARE @Letters TABLE (
    MyChar CHAR(1) PRIMARY KEY
)
DECLARE @N INT
SET @N=0
WHILE @N<26 BEGIN
    INSERT @Letters (MyChar) VALUES ( CHAR( @N + 65) )
    SET @N = @N + 1
END
-- SELECT * FROM @Letters ORDER BY 1

SELECT A.MyChar, B.MyChar, C.MyChar, D.MyChar
FROM @Letters A, Letters B, Letters C, Letters D
ORDER BY 1,2,3,4

Преимущества заключаются в следующем: он легко расширяется с использованием капитала/строчной буквы или использует неанглийские латинские символы (думаю, "С" или cedille, eszets и т.п.), и вы все равно будете получать упорядоченный набор, только нужно добавьте сортировку. Кроме того, SQL Server будет выполнять это немного быстрее, чем LINQ на одноядерном компьютере, на многоядерных (или многопроцессорных системах) выполнение может быть параллельно, получая еще больший импульс.

К сожалению, он застрял для конкретного случая с 4 буквами. Рекурсивное решение lassevk является более общим, пытаясь сделать общее решение в T-SQL, обязательно подразумевает динамический SQL со всеми его опасностями.

Ответ 6

Python!

(Это всего лишь взломать, не слишком серьезно относиться к мне: -)

# 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

Ответ 7

Haskell!

replicateM 4 ['A'..'Z']

рубин!

('A'*4..'Z'*4).to_a

Ответ 8

Это рекурсивная версия тех же функций в С#:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ConsoleApplication1Test
{
    class Program
    {
        static char[] my_func( char[] my_chars, int level)
        {
            if (level > 1)
                my_func(my_chars, level - 1);
            my_chars[(my_chars.Length - level)]++;
            if (my_chars[(my_chars.Length - level)] == ('Z' + 1))
            {
                my_chars[(my_chars.Length - level)] = 'A';
                return my_chars;
            }
            else
            {
                Console.Out.WriteLine(my_chars);
                return my_func(my_chars, level);
            }
        }
        static void Main(string[] args)
        {
            char[] text = { 'A', 'A', 'A', 'A' };
            my_func(text,text.Length);
            Console.ReadKey();
        }
    }
}

Печатает от AAAA до ZZZZ

Ответ 9

Упрощенный Python!

def getWords(length=3):
    if length == 0: raise StopIteration
    for letter in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
        if length == 1: yield letter
        else:
            for partialWord in getWords(length-1):
                yield letter+partialWord

Ответ 10

Javascript!

var chars = 4, abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", top = 1, fact = [];
for (i = 0; i < chars; i++) { fact.unshift(top); top *= abc.length; }
for (i = 0; i < top; i++)
{
    for (j = 0; j < chars; j++) 
        document.write(abc[Math.floor(i/fact[j]) % abc.length]);
    document.write("<br \>\n");
}

Ответ 11

Используйте то, что автоматически Googles для каждой отдельной комбинации букв, а затем посмотрите, есть ли больше ".sz" или ".af", а затем ".com" попадает в пять первых результатов...;)

Серьезно, то, что вы ищете, может быть Tries (структура данных), хотя вам все равно нужно заполнить вещь, которая, вероятно, намного сложнее...

Ответ 12

Очень простой, но удивительный код, который генерирует все слова из 3 и 4 букв английского языка

#include <iostream>
using namespace std;
char alpha[26]={'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'}
int main() {
int num;
cin >> num;
if (num == 3) { //all 3 letter words
    for (int i = 0; i <= 25; i++) {
        for (int o = 0; o <= 25; o++) {
            for (int p = 0; p <= 25; p++) {
                cout << alpha[i] << alpha[o] << alpha[p] << " ";
            }
        }
    }
}
else if (num == 4) { //all 4 letter words
    for (int i = 0; i <= 25; i++) {
        for (int o = 0; o <= 25; o++) {
            for (int p = 0; p <= 25; p++) {
                for (int q = 0; q <= 25; q++) {
                    cout << alpha[i] << alpha[o] << alpha[p] << alpha[q] << " ";
                }
            }
        }
    }
}
else {
    cout << "Not more than 4"; //it will take more than 2 hours for generating all 5 letter words
  }
}