2008-11-23 5 views
7

Я пытаюсь создать алгоритм в C#, который производит следующие выходные строки:Что такое хороший способ выяснить все возможные слова заданной длины

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

Что является лучшим способом для достижения этой цели?

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

Что вы пытаетесь сделать? Возможно, лучше создать список лениво, в зависимости от вашего ответа. – 2008-11-23 17:28:33

+0

@John the Statistian: Использование блоков итератора * делает * генерировать список лениво. – 2008-11-23 17:50:05

+0

Это может быть полезно при создании наивной логики грубой силы. Однажды я сделал что-то подобное для класса, где нам пришлось сломать шифр. Аналитическая техника была легкой, поэтому я также написал программу, которая использовала всю компьютерную лабораторию в колледже в течение нескольких часов раньше одного субботнего утра. :) – 2008-11-23 18:03:18

ответ

17

хорошо, если длина является константой 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; 
    } 
} 
+0

Я почти ниспроверг это, как только увидела шаблон в первом предложении. Второй кажется ОК. – Svante 2008-11-23 21:29:36

15

Всегда есть обязательная реализация 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; 
} 

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

+0

, если это решение правильно, это удивительное решение. спасибо за понимание C#. я должен купить одну из книг jon skeet, когда он пишет о C# 5.0 с метапрограммированием :) – 2008-11-23 18:38:02

1

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

Скажите «Письма» - это стол с одним полем, MyChar, 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 со всеми его опасностями.

+0

вы не можете победить haskell: print [a: b: c: d: [] | пусть q = ['a' .. 'z'], a <- q, b <- q, c <- q, d <- q] – 2008-11-23 19:14:35

0

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"); 
} 
1

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 
1

Haskell!

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

Ruby!

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

Просто Coment для Garry Shutler, но я хочу код расцветку:

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

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

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

0

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

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

1

Это является рекурсивной версии одних и тех же функций в C#:

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

1

Упрощенный 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 
0

Очень простой, но удивительный код, который генерирует все слова 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 
    } 
}