字母表的每个排列最多29个字符?

我正在尝试编写一个程序,该程序将生成一个文本文件,其中包含从一个字符到二十九个字符的字母表的每个可能的排列。 我选择了29作为最长的英语单词,每个人都知道这是一个长度为28个字符的反歧视法。 有更长的,但它们主要是技术性和模糊性。

我意识到这会产生大量的字符串。 但是我不知道从哪里开始,甚至不知道如何计算出这将产生多少组合。

请回答有关PHP, Processing ,C ++或Java的解决方案(我只熟悉那些,PHP是首选,但可能没有最好的,我应该想象)。

或者甚至只是伪代码/想法将不胜感激。

此外,在有人说出来之前,这不是为了暴力强迫或类似的东西。 我是一名艺术家,虽然有点不为人知,但我的概念模糊不清。

“置换”一词通常意味着每个字母只出现一次,因此不可能产生超过26个字母的任何排列。 无论如何,由于生成的字符串数量太大,您可以使用随机字符串(以下是C代码):

char s[30]; int p; for (;;) // repeat forever: you cannot use a realistic iteration limit anyway { for (p = 0; p < 29; ++p) s[p] = 'a' + rand() % 26; s[29] = '\0'; puts(s); } 
 void out_perms(std::string word) { std::vector indexes(word.size()); for (size_t i = 0; i < indexes.size(); ++i) indexes[i] = i; do { for (size_t i = 0; i < indexes.size(); ++i) std::cout << word[indexes[i]]; std::cout << std::endl; } while (std::next_permutation(indexes.begin(), indexes.end())); } int main(int, char**) { out_perms("asdfg"); } 

有关示例输出,请参见http://codepad.org/6lQTPQrG

显然,外部for循环用于单词中的字符数。 然后,您只需创建具有该长度的字符串。 对于长度为5,您从“AAAAA”开始,然后是“AAAAB”,“AAAAC”。

一旦你点击“Z”,你就回去向左移动角色,即“AAAAZ”变成“AAABA”,“AAAZZ”变成“AABAA”。 一旦你点击“ZZZZZ”,你就完成了内循环,外循环将以“AAAAAA”开始。

这是一个简单的未经测试的C ++程序,通过在Base 26中计数来创建单词:

 #include  #include  int main(void) { //---------------------------------------------------------- // Print permuations of strings of letters up to length 5. // Use base 26 arithmetic. //---------------------------------------------------------- const unsigned int MAX_ITERATIONS = 26 * 26 * 26 * 26 * 26; std::string word = "A"; for (unsigned int i = 0; i < MAX_ITERATIONS; ++i) { //------------------------------------------------------ // Print the word //------------------------------------------------------ std::cout << word << std::endl; //------------------------------------------------------ // Increment the word, using base 26 arithmetic. // A, B, C, ..., Z. // AA, BA, CA, ..., ZA, AB, BB, CB, DB, ..., ZZ. // AAA, BAA, CAA, ..., ZAA, ABA, BBA, CBA, DBA, ..., ZZZ. //------------------------------------------------------ bool carry_generated = false; unsigned int digit = 0; do { carry_generated = false; if (word[digit] < 'Z') { ++word[digit]; break; } word[digit++] = 'A'; if (word.length() == digit) { word += "A"; break; } carry_generated = true; } while (carry_generated && (digit < 5)); } return 0; } 

通过在打印之前检查单词列表(也称字典),可以减少打印的单词数。 如果单词在单词列表中,则打印它。

字长为29的最大问题是数量。 数量溢出标准C ++无符号整数的范围。 需要使用Big Int库。 下一个问题是处理每个组合所需的时间。 将每次迭代的数量乘以1微秒(一种更糟糕的情况)并减少到几天,几小时,几分钟和几秒。 也许可能需要几年时间。

使用PHP的Perl样式字符递增。

 set_time_limit(0); $perm = 'A'; $endTest = str_repeat('Z',28).'A'; while ($perm != $endTest) { echo $perm++,"\n"; } 

从命令行运行脚本,这样就不会遇到Web服务器超时; 然后坐下来等待几年才能完成

 function p($length, $partial) { if ($length == 0) return $partial; $ans = array(); foreach (range('a', 'z') as $i) { $ans[] = p($length -1, $partial . $i); } return $ans; } $top = 3; //$f = fopen('out.txt'); for ($l = 1; $l < $top+1; $l++) { print_r(p($l), ''); //fwrite($p($l), ''); } 

如果你想将$top设置$top 29并试一试,请继续。 我不打算。

编辑 - print_r(p($l), ''); ---> print_r(p($l, ''));

PHP通过容忍错误让我印象深刻。 错过了我的p '必需'参数? 没问题,它只是空字符串某种方式(或零,或假,情况依赖)。 print_r的第二个论点? 没有区别,无论如何都被视为默认的false

编辑

我不知道我到底在做什么。 p的不同返回类型非常奇怪,并且将返回具有奇怪结构的复合数组。

无论如何,这是一个更好的解决方案

 $lengthDesired = 29; for($i='a'; $i != str_pad('',$lengthDesired+1,'a'); $i++) echo $i .', '; 

这是一个用java编写的排列生成器http://www.merriampark.com/perm.htm 。

然而正如他提到的那样

  //----------------------------------------------------------- // Constructor. WARNING: Don't make n too large. // Recall that the number of permutations is n! // which can be very large, even when n is as small as 20 -- // 20! = 2,432,902,008,176,640,000 and // 21! is too big to fit into a Java long, which is // why we use BigInteger instead. //---------------------------------------------------------- 

由于你的n是29,你将等待很长很长时间。 它太大了,因为EboMike试图在他的评论中告诉你。

就在我的头顶(PHP)。

 $index = 0; while(1) { $output_string = ''; $base_26 = (string)base_convert($index, 10, 26); if (strlen($base_26) > 29) break; for ($i = 0; $i < strlen($base_26); $i++) { $output_string .= chr(65 + base_convert($base_26[$i], 26, 10)); } $index++; echo $output_string; } 

这就是我要做的:

 #include  void printWords(std::string& word, int index, int last) { std::cout << word << "\n"; if (index != last) { for(char loop = 'a'; loop <= 'z'; ++loop) { word[index] = loop; printWords(word, index+1, last); } word[index] = ' '; } } int main() { std::string word(" "); // 29 space printWords(word,0,word.length()); } 

应该解决这个问题的Java解决方案:

 public void characterPermutations(int length, LinkedList permutations) { if(length > 1) { characterPermutations(length - 1, permutations); ListIterator iterator = permutations.listIterator(); while(iterator.hasNext()) { String permutation = iterator.next(); for(char c = 'a'; c <= 'z'; c++) { iterator.add(c + permutation); } } } else { for(char c = 'a'; c <= 'z'; c++) { permutations.add(c + ""); } } } 
 public class hii { public static void main(String[] args){ String[] database = {"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"}; for(int i=1; i<=database.length; i++){ String[] result = getAllLists(database, i); for(int j=0; j 

我能想到的最简单的方法是在伪代码中将每个排列从1个char变为29个chars:

 loop from i = 1 to 26^29 or 27^29 if you want to include spaces { convert i to base 26 or 27; translate each number to the corresponding letter; } 

即使你可以将它存储在磁盘上,就像thirydot指出的那样,你也没时间做这件事了。

只需生成(而不是存储)所有6个字母的可能性,我的计算机需要24秒:

 $ time perl letters.pl real 0m24.837s user 0m24.765s sys 0m0.030s 

每个单词7.7X10 ^ -8s,这意味着它需要8.4×10 ^ 33s或2.6×10 ^ 26s才能完成。

您需要更多地考虑您的算法。