找出给定长度的所有可能单词的好方法是什么

我正在尝试在C#中创建一个算法,它产生以下输出字符串:

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

完成此任务的最佳方法是什么?

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

好吧,如果长度是常数4,那么这将处理它:

 public static IEnumerable 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 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; } } 

总是有强制性的LINQ实现。 最有可能是垃圾性能,但是从什么时候开始使用酷炫的新function呢?

 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’现在是一个包含AAAA到ZZZZ的IQueryable。

编辑:

好的,所以我不禁要知道应该可以使用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 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 AddLevel(IQueryable current, string[] characters) { return from one in current from character in characters select one + character; } 

对Sequence方法的调用产生与之前相同的AAAA到ZZZZ列表,但现在您可以更改使用的字典以及生成的单词的长度。

只是对Garry Shutler的讽刺,但我想要代码着色:

你真的不需要使它成为IQuaryable,既不是排序,所以你可以删除第二种方法。 一步转发是使用Aggregate进行交叉产品,它最终如下:

 IEnumerable 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的诺贝尔奖!

GNU Bash!

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

python!

(这只是一个黑客,不要’太认真了:-)

 # Convert a number to the base 26 using [AZ] 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 

在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具有其所有危险。

哈斯克尔!

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

ruby!

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

更简单的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 

这是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

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("
\n"); }

使用自动Googles为每个单个字母组合的东西,然后看看是否有更多“.sz”或“.af”命中,然后“.com”命中五个第一个结果……;)

说真的,你正在寻找的可能是Tries(数据结构),尽管你仍然需要填充可能更难的东西……

一个非常简单但很棒的代码,可生成3个和4个英文字母的所有单词

 #include  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 } }