Каждая перестановка алфавита до 29 символов?

Я пытаюсь написать программу, которая будет генерировать текстовый файл со всеми возможными перестановками алфавита от одного символа до двадцати девяти символов. Я выбрал 29 как самое длинное английское слово, которое все знают, — это антидезистестментарианство, длина которого составляет 28 символов. Есть более длинные, но они в основном очень технические и малопонятные.

Я понимаю, что это создаст огромное количество строк. Однако я понятия не имею, с чего начать или даже как выяснить, сколько комбинаций это сгенерирует.

Ответы, пожалуйста, для решений в PHP, Processing, C++ или Java (я только знакомый с ними, PHP предпочтительнее, но, вероятно, не лучший для этого, как мне кажется).

Или даже просто псевдокод/идеи будут оценены.

Кроме того, прежде чем кто-то это скажет, это не для грубой силы или чего-то в этом роде. Я художник, хоть и несколько неизвестный и непонятный своими понятиями.


person logic-unit    schedule 05.01.2011    source источник
comment
Надеюсь, вы понимаете, насколько большим может быть этот текстовый файл. Лучше купите еще несколько жестких дисков.   -  person EboMike    schedule 06.01.2011
comment
Если вы просто сделаете все возможные перестановки 29-символьных слов, это будет 26 в степени 29. Это примерно 1e41.   -  person EboMike    schedule 06.01.2011
comment
Да, это в моем списке дел. Извините, извините за мою плохую математику, что это за написанное число?   -  person logic-unit    schedule 06.01.2011
comment
Объединенный объем памяти всей нашей планеты не мог вместить этот список.   -  person thirtydot    schedule 06.01.2011
comment
Ой. Один на будущее, я думаю.   -  person logic-unit    schedule 06.01.2011
comment
Ладно, может я не ясно выразился. У вас есть жесткий диск на 1 ТБ? 1e41 байт — это 1000000000000000000000000000000 ТБ. На самом деле я ошибся - 1е41 это просто количество "комбинаций". Вам придется умножить это на 30. Ба, что еще за ноль?   -  person EboMike    schedule 06.01.2011
comment
Хорошо, кроме места для хранения, как будет работать программа. Скажем, до 10 символов?   -  person logic-unit    schedule 06.01.2011
comment
Это много терабайт. Наверное, поэтому никто этого и не сделал, я думаю.   -  person logic-unit    schedule 06.01.2011
comment
Может быть, я неправильно прочитал ваш вопрос - что вы пытаетесь сделать? Перетасовать буквы, как в моем ответе? Или выполните одноалфавитную замену вашего слова для каждой возможной замены, как в en.wikipedia.org/wiki/ Substitution_cipher#Простая_подстановка?   -  person etarion    schedule 06.01.2011
comment
Мы говорим об перестановках одного слова или комбинациях букв алфавита? Из вопроса мне непонятно.   -  person Matteo Italia    schedule 06.01.2011
comment
Привет etarion, спасибо за ваш ответ. Я пытаюсь создать каждую уникальную комбинацию A-Z от одной буквы до двадцати девяти букв. По сути, каждое слово, которое могло бы существовать или существует, до двадцати букв.   -  person logic-unit    schedule 06.01.2011
comment
Что касается искусства, я лично не вижу смысла в таком большом списке случайных персонажей, что никто никогда не сможет увидеть его все.   -  person brian_d    schedule 06.01.2011
comment
@Matteo Italia, я думаю, что на самом деле это могут быть комбинации.   -  person logic-unit    schedule 06.01.2011
comment
@brian_d ну, это субъективное поле. Я на самом деле не обсуждаю концепцию, просто спрашиваю, как это можно сделать.   -  person logic-unit    schedule 06.01.2011
comment
@logic-unit: ну, значит, это комбинации; они должны быть 26+26^2+26^3+...+26^29=26^30-1 комбинаций (IIRC).   -  person Matteo Italia    schedule 06.01.2011
comment
@logic-unit: взгляните на мой ответ: stackoverflow.com/questions/1991361/. Имейте в виду, что очевидно, что этот код будет счастливо работать в течение сотен лет, прежде чем ваша работа будет выполнена.   -  person Matteo Italia    schedule 06.01.2011
comment
Хорошо, учитывая, что на моей машине получение 26 ^ 6 комбинаций (отбрасывая ввод-вывод) выполняется за 9,48 с, выполнение всех 26 ^ 30 (-1) должно занять 26 ^ 30/26 ^ 6 * 9,48 = 26 ^ 24 * 9,48. =86331381095212797790462237062180372,48 с, что составляет примерно 2,7*10^27 лет. Я надеюсь, что у вас есть хороший ИБП, чтобы поддерживать работу вашего ПК, когда Sun полностью прекратит свое существование.   -  person Matteo Italia    schedule 06.01.2011
comment
@Matteo Italia спасибо, это выглядит очень интересно. Хотя не уверен, что у меня есть сотни лет. Возможно, это семейная реликвия.   -  person logic-unit    schedule 06.01.2011
comment
Поскольку это художественный проект, возможно, результат не нужно сохранять. Возможно, он мог бы мигать светодиодом, направленным на Большое Магелланово Облако или что-то в этом роде?   -  person Tony Park    schedule 06.01.2011
comment
@Tony Park, спасибо, да, я просто пытался придумать альтернативы, так как моя идея маленькой книги в кожаном переплете провалилась.   -  person logic-unit    schedule 06.01.2011
comment
На самом деле в какое-то время я думал о создании веб-сайта, который предоставлял бы все возможные черно-белые изображения определенного размера (генерируя их с отметкой времени запроса), возможно, позволяя пользователям сохранять свои любимые изображения. Я думаю, что такая штука была бы веселее, так как бессмысленное слово ни о чем не говорит, а в странном образе всегда можно найти какой-то странный смысл.   -  person Matteo Italia    schedule 06.01.2011
comment
@Matteo Italia Я не думал об использовании изображений. Хотя бы слово без значения имеет бесконечный потенциал.   -  person logic-unit    schedule 06.01.2011
comment
@logic-unit: ИМО было бы лучше и более запоминающимся. Кстати, вы пытаетесь добиться чего-то подобного? en.wikipedia.org/wiki/The_Nine_Billion_Names_of_God :D   -  person Matteo Italia    schedule 06.01.2011
comment
@Matteo Italia спасибо за ссылку, мне нужно будет это прочитать. Думаю, в некотором смысле да, хотя у меня нет никаких теистических наклонностей. Да, я согласен с изображениями, вероятно, стоит изучить оба. На самом деле, вероятно, существует множество вариаций этой идеи.   -  person logic-unit    schedule 06.01.2011
comment
@логическая единица; что, если вы напечатаете первый миллион строк в своей книге, затем художественное изображение взрыва в формате ascii, за которым следует алгоритм? :-)   -  person Tony Park    schedule 06.01.2011
comment
@логическая единица; с некоторых точек зрения нет никакой разницы между выводом и алгоритмом, это может быть забавной идеей для программиста/художника — и я только что сказал «перспектива»? Теперь у меня есть изображение большой струны, уходящей вдаль.   -  person Tony Park    schedule 06.01.2011
comment
@ Тони Парк, хех, хорошая идея. Или я мог бы просто напечатать 100 книг случайных комбинаций и надеяться, что никто не проверит.   -  person logic-unit    schedule 06.01.2011
comment
Есть ли способ сгенерировать только одну комбинацию в последовательности по запросу? Значит, используя алгоритм, человек может просмотреть любую из всех комбинаций без необходимости генерировать их все и записывать в файл?   -  person logic-unit    schedule 06.01.2011
comment
@логическая единица; но было бы здорово, если бы кто-нибудь проверил?   -  person Tony Park    schedule 06.01.2011
comment
@logic-unit: альтернативой было бы получить обезьяну с пишущей машинкой и дать ей бесконечное время. Расскажите нам, когда вы получили полное собрание сочинений Шекспира. :)   -  person Matteo Italia    schedule 06.01.2011
comment
@logic-unit: ну, комбинация букв - это просто причудливый способ записи числа (вы пишете его с основанием 26 вместо основания 10); для этого можно использовать обычные алгоритмы изменения базы. Но если бы вы спросили у пользователя номер комбинации, чтобы вернуть ему эквивалентную строку, это было бы мошенничеством, вы бы просто изменили основу, в которой выражается его число. :)   -  person Matteo Italia    schedule 06.01.2011
comment
Одна комбинация? Легкий. В основном возьмите свой лучший ответ и игнорируйте цикл. Но не в книге :-)   -  person Tony Park    schedule 06.01.2011
comment
О, да! Хотя идея книги кажется лучше, возможно, немного более глубокой. Такого рода проблемы, вероятно, будут легкими через 20 лет ...   -  person logic-unit    schedule 06.01.2011
comment
Спасибо всем за ваш вклад, мне нужно подумать об этом некоторое время.   -  person logic-unit    schedule 06.01.2011
comment
@logic-unit просто запоздалая мысль. вас интересует каждая перестановка или каждое слово, которое может иметь значение сейчас или в будущем? например, нужны ли вашим перестановкам по крайней мере гласная через каждые x согласных, или они могут быть просто какой-то аббревиатурой, бессмысленным словом или зашифрованным кодом?   -  person brian_d    schedule 06.01.2011
comment
@brian_d спасибо за ваш ответ - запоздалые мысли всегда приветствуются. я еще не зашел так далеко. я думаю, что хочу создать комбинации букв, которые являются или могут быть словом на английском языке. я не уверен в шаблоне или структуре, которой следуют все английские слова - что-то, что мне нужно изучить. Я должен представить, что это несколько уменьшит число 26 в степени 29?   -  person logic-unit    schedule 07.01.2011
comment
@logic-unit Я думаю, что это, безусловно, уменьшит размер набора результатов, хотя генератор все равно будет большим   -  person brian_d    schedule 07.01.2011


Ответы (12)


Слово «перестановка» обычно означает, что каждая буква появляется ровно один раз, поэтому было бы невозможно сгенерировать какую-либо перестановку с более чем 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);
}
person anatolyg    schedule 05.01.2011
comment
Не очень систематично, да :) - person EboMike; 06.01.2011
comment
это неверно, вы дали определение комбинации, перестановка - это конструкция с использованием комбинации, например: комбинация букв a, b и c может составить перестановки abc или aabbcc или abbbc и т. д. - person ; 06.01.2011
comment
Ведь вы даете определение комбинации, а не перестановки. В комбинации abc и acb одинаковы. Но в перестановке abc и acb - это 2 разных расположения. - person Lynnell Neri; 09.12.2015

void out_perms(std::string word) {
    std::vector<int> 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, например вывод.

person etarion    schedule 05.01.2011
comment
Я интерпретировал каждую возможную перестановку алфавита как любую возможную комбинацию букв в алфавите, т. е. от ааааа до ззззз. - person EboMike; 06.01.2011

Очевидно, что внешний цикл for предназначен для количества символов в вашем слове. Затем вы просто создаете строки такой длины. Для длины 5 вы начинаете с «AAAAA», затем «AAAAB», «AAAAC».

Как только вы нажмете «Z», вы вернетесь назад и переместите символ слева от вас вверх, т. Е. «AAAAZ» станет «AAABA», а «AAAZZ» станет «AABAA». Как только вы нажмете «ZZZZZ», вы закончите внутренний цикл, а внешний цикл начнется с «AAAAAA».

person EboMike    schedule 05.01.2011
comment
Я считаю, что эту концепцию легче понять, если считать по основанию 26. Первая цифра идет от A до Z, затем AA, AB, ..., AZ, затем BA и так далее. - person Thomas Matthews; 06.01.2011
comment
Да, то же самое, что считать от 1 до 999999, за исключением того, что вы используете буквы как цифры. - person EboMike; 06.01.2011

Вот простая непроверенная программа на C++, которая создает слова, считая в базе 26:

#include <string>
#include <iostream>

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 микросекунду за итерацию (что-то в худшем случае) и уменьшите до дней, часов, минут и секунд. Возможно, потребуются годы.

person Thomas Matthews    schedule 05.01.2011
comment
Спасибо, Томас, это отличный ответ. Да, я не думал об этом, превышающем целочисленную длину. - person logic-unit; 06.01.2011
comment
Моя приблизительная оценка составляет 8,9E + 29 лет, предполагая 1 микросекунду на итерацию и всего 26 ^ 30 (26 в степени 30) итераций (должно быть на единицу меньше, но это незначительно в таком большом числе). Я могу ошибаться... - person Thomas Matthews; 06.01.2011

Использование увеличения символов в стиле PHP Perl.

set_time_limit(0);

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

Запустите скрипт из командной строки, чтобы не превысить тайм-аут веб-сервера; затем сядьте и подождите несколько лет, пока он не завершится

person Mark Baker    schedule 05.01.2011
comment
Хорошее решение, спасибо. Я включу чайник, пока он работает. - person logic-unit; 06.01.2011

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 на 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 .', ';
person jon_darkstar    schedule 06.01.2011

Вот генератор перестановок, написанный на 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 лет, вы будете ждать очень-очень долго. Он слишком большой, как пытается сказать вам ЭбоМайк в своих комментариях.

person brian_d    schedule 05.01.2011
comment
Да, я знал, что он будет большим. Не совсем понял, насколько большой. Я уверен, что это возможно, чтобы отобразить эту информацию в той или иной форме. Это может быть более сложной задачей, чем создание комбинаций. - person logic-unit; 06.01.2011

только что пришло мне в голову (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;
}
person dqhendricks    schedule 05.01.2011
comment
сценарий, скорее всего, в конечном итоге сломается. - person dqhendricks; 06.01.2011

Вот что я бы сделал:

#include <iostream>

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());
}
person Martin York    schedule 06.01.2011

Java-решение, которое должно помочь:

public void characterPermutations(int length, LinkedList<String> permutations) {
    if(length > 1) {
        characterPermutations(length - 1, permutations);

        ListIterator<String> 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 + "");
        }
    }
}
person Kurt Kaylor    schedule 06.01.2011

Самый простой способ, который я могу придумать, чтобы получить каждую перестановку от 1 до 29 символов в псевдокоде:

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;
}
person 182764125216    schedule 05.01.2011

Даже если бы вы могли сохранить это на диске, как указал thyrydot, у вас не хватило бы времени на это.

Просто генерация (а не сохранение) всех 6-буквенных возможностей на моем компьютере заняла 24 секунды:

$ time perl letters.pl

real    0m24.837s
user    0m24.765s
sys     0m0.030s

Что составляет 7,7x10^-8s на слово. Это означает, что для этого потребуется 8,4x10^33s или 2,6x10^26 лет.

Вам нужно больше думать о своем алгоритме.

person miked    schedule 10.05.2011