Можно ли сгенерировать Pangram из заданного списка слов?
Панграмма - это предложение, использующее каждую букву алфавита хотя бы один раз.
Можно ли сгенерировать самую короткую Панграмму из данного списка слов?
Допустим, у меня есть список слов, как это
cat monkey temp banana christmas
fast quick quickest jumping
white brown black blue
fox xor jump jumps oven over
now the is was
lazy laziest crazy
dig dog joker mighty
И, как для создания списка возможных панограмм, как следующие
the quick over lazy jumps fox dog brown
brown dog fox jumps lazy over quick the
quick brown fox jumps over the lazy dog
Грамматику и порядок слов пока не нужно рассматривать (я собираюсь сделать это не на английском языке)
Любые идеи, алгоритмы, коды, ссылки, будут с благодарностью!
PS: это не домашняя работа
3 ответа
Самый простой способ создать все возможные панграммы из списка слов - это, вероятно, сгенерировать все возможные комбинации слов из списка, а затем для каждого из них проверить, является ли это панграммой. Для проверки пройдитесь по строке и установите значение bool равным true для каждой буквы в строке. В конце концов, это панграмма, если все значения bool установлены на true.
Более эффективный метод, вероятно, состоит в том, чтобы пройтись по каждому слову и установить массив bools (или набор битов, например, в 32-битном int) вместе с длиной слова. Затем вы можете найти биты, которые вместе производят значение со всеми установленными 26 битами, и у вас есть панграмма.
Когда вы объединяете панграмму, вы можете добавить проверку границ, поэтому, если добавление слова сделает потенциальную панграму длиннее текущей кратчайшей (если таковая имеется), вы немедленно прекратите эту проверку. Если вы начнете с сортировки слов по длине, в ту минуту, когда вы нажмете более длинную комбинацию, вы можете прекратить весь этот набор попыток и перейти к следующей возможности.
Если вы хотите получить еще более изощренные знания об этом, вы можете начать с создания набора битов того же типа, что и выше. Затем возьмите их и сложите вместе биты, чтобы определить, какие буквы встречаются в наименьшем количестве слов. Когда вы начинаете генерировать потенциальную панграмму, вы знаете, что она должна включать одно из этих слов. Например, в приведенном выше списке "ленивый", "ленивый" и "сумасшедший" кажутся единственными, которые включают "z", так что вы сразу знаете, что каждая панграмма должна включать одно из этих трех слов. Ни одно из них не включает "q", и единственные слова, которые включают "q", кажутся "быстрыми" и "самыми быстрыми", поэтому (опять же) каждая панграмма должна включать одно из этих двух (конечно, я собираюсь от ручного осмотра здесь, так что я мог пропустить ни слова). Таким образом, каждая возможная панграмма из этого списка включает (и может начинаться с): (быстрая | быстрая) (ленивая | ленивая | сумасшедшая).
Вы также можете рассмотреть возможность предварительной обработки списка слов: любое слово, которое длиннее другого, но не содержит хотя бы одной буквы, отсутствующей в другой, может быть немедленно удалено. В качестве гипотетического примера, если у вас есть "ab" и "abab", вы знаете, что "abab" никогда не может привести к более короткой панграмме, чем "ab", поэтому вы могли бы также немедленно исключить ее из списка.
Конечно. Вот один алгоритм:
- Пусть Lw будет заданным списком слов.
- Пусть Ld будет списком различных слов в Lw.
- Пусть Lc будет списком всех возможных комбинаций с использованием слов из Ld. Если Ld содержит n элементов, Lc будет содержать 2n элементов.
- Пусть P будет самой короткой панграммой (желаемый результат). Изначально P будет пустым.
- Итерировать по каждому элементу (комбинации) в Lc. В каждой итерации:
- Пусть C будет текущей рассматриваемой комбинацией.
- Проверьте, является ли C панграммой.
- Если C является панграммой, проверьте, является ли P пустым или C короче, чем P.
- Если P пусто или если C короче P, пусть P будет C
- Если C является панграммой, проверьте, является ли P пустым или C короче, чем P.
Идеи для поиска приближенных решений:
- определить частоту букв вашего набора
- забить каждое слово
- добавляйте слова с наивысшей оценкой, пока не получите все буквы
Оценка слов может выглядеть примерно так:
score = 0
foreach unique letter in word
score += 1/letter_frequency[letter]
score /= word.length