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

时间:2008-11-23 17:18:40

标签: c# string algorithm iterator

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

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

实现这一目标的最佳方法是什么?

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

12 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分: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'现在是一个包含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<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列表,但现在您可以更改使用的字典以及生成的字词的长度。

答案 2 :(得分:5)

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

你真的不需要将它设为IQuaryable,也不需要排序,所以你可以删除第二种方法。一步转发就是使用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);

Anders应该获得Linq的诺贝尔奖!

答案 3 :(得分:2)

GNU Bash!

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

答案 4 :(得分: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具有其所有危险。

答案 5 :(得分: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

答案 6 :(得分:1)

的Haskell!

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

红宝石!

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

答案 7 :(得分: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

答案 8 :(得分: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

答案 9 :(得分: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");
}

答案 10 :(得分:0)

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

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

答案 11 :(得分: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
  }
}