我正在尝试在 C# 中创建一个生成以下输出字符串的算法:
AAAA
AAAB
AAAC
...and so on...
ZZZX
ZZZY
ZZZZ
实现这一目标的最佳方法是什么?
public static IEnumerable<string> GetWords()
{
//Perform algorithm
yield return word;
}
好吧,如果长度是常数 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;
}
}
总是有强制性的 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 列表,但现在您可以更改使用的字典以及生成的单词的长度。
只是对 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);
安德斯应该因为 Linq 的事情获得诺贝尔奖!
GNU 重击!
{a..z}{a..z}{a..z}{a..z}
受到 Garry Shutler 回答的启发,我决定用 T-SQL 重新编码他的回答。
假设“Letters”是一个只有一个字段 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 及其所有危险。
Python!
(这只是一个 hack,不要把我当回事 :-)
# 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
哈斯克尔!
replicateM 4 ['A'..'Z']
红宝石!
('A'*4..'Z'*4).to_a
这是 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
更简单的 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
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");
}
使用自动谷歌搜索每个字母组合的东西,然后查看是否有更多的“.sz”或“.af”点击然后“.com”点击五个第一个结果......;)
说真的,您正在寻找的可能是尝试(数据结构),尽管您仍然需要填充可能更难的东西......
一个非常简单但很棒的代码,可以生成所有 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
}
}