Я встревожился растущей ненавистью к пробелам, и этот ответ вдохновил меня на то, чтобы код Морзе был защищен от этого коварного удаления пробелов.
Итак, ваша задача будет состоять в том, чтобы создать программу, которая сможет успешно переводить азбуку Морзе со всеми удаленными пробелами.
Правила:
На входе будет строка, состоящая только из тире и точек (ASCII 2D и 2E). Вывод не определен для ввода, содержащего любые другие символы. Не стесняйтесь использовать любой метод, удобный для вашего языка, для получения ввода (стандартный ввод, текстовый файл, приглашение пользователя и т. Д.). Можно предположить, что ввод азбуки Морзе состоит только из букв AZ, и соответствующие цифры или знаки препинания не требуются.
Вывод должен включать только слова, содержащиеся в этом файле словаря (опять же, не стесняйтесь использовать любой удобный метод для доступа к файлу словаря). Все действительные декодирования должны быть выведены на стандартный вывод, и должны быть использованы все точки и тире на входе. Каждое совпадающее слово в выходных данных должно быть разделено пробелом, а каждое возможное декодирование должно быть отделено новой строкой. Вы можете использовать верхний регистр, нижний регистр или смешанный регистр как удобно.
Все ограничения на стандартные лазейки применяются с одним исключением, как отмечено выше, вы можете получить доступ к файлу словаря, на который есть ссылка в требовании 2, через интернет-соединение, если вы действительно этого хотите. Сокращение URL приемлемо, я считаю, что goo.gl/46I35Z , вероятно, самый короткий.
Это код гольф, самый короткий код выигрывает.
Примечание. При публикации файла словаря на Pastebin все окончания строк изменились на последовательности в стиле 0A 0E в стиле Windows. Ваша программа может предполагать окончания строки только с 0A, только 0E или 0A 0E.
Тестовые случаи:
Входные данные:
......-...-.. ---. ----- ...-..- ..
Вывод должен содержать:
Привет, мир
Входные данные:
...,. ----- .... ----- ... - .. - ... --- .. - ...-.... ... - ...-.. ---- ... -. ----....-..
Вывод должен содержать:
программирование головоломок и код гольфа
Входные данные:
-..... - ...-...-.. -.. ...., .... --- --- ---- ..-.- --.. --- -. .... --- ...-...-......-... --- ... --- ..-- ---.
Вывод должен содержать:
Быстрая коричневая лиса прыгает через ленивую собаку
AN (.- -.)
иEG (. --.)
?Ответы:
Рубин, 210
Если существует такая практика, как «чрезмерная игра в гольф», я подозреваю, что принял участие в этот раз. Это решение генерирует массив массивов повторяющихся перестановок всех слов словаря , от длины 1 до длины ввода. Учитывая, что «a» является самым коротким словом в файле словаря, а его код состоит из двух символов, было бы достаточно генерировать перестановки длиной до половины размера ввода, но добавление
/2
равнозначно многословности в этой области, поэтому я воздержался.После того, как массив перестановок был сгенерирован ( примечание : он имеет длину 45404 104 в случае входных данных панграмматического примера), каждый массив перестановок объединяется, и его буквенные символы заменяются их эквивалентами кода Морзе через довольно удобный
(Regexp, Hash)
вариант#gsub
Способ; мы нашли правильное декодирование, если эта строка равна входу.Словарь читается (несколько раз) из файла с именем "d", и ввод не должен содержать символ новой строки.
Пример выполнения (со словарем, который даст программе шанс на сражение до конца перед тепловой смертью вселенной):
источник
Haskell, 296 символов
Объяснение элементов:
main
читает словарь, читает stdin, выполняет&
и форматирует выходные данные&
с соответствующим пробелом.(replicate 97"X"++words".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..")!!)
(выражение внутри определения&
) представляет собой список, индексы которого представляют собой коды символов (97 - это код'a'
), а значения - последовательности Морзе.!
(функция, называемая инфиксным оператором) сопоставляет строку с префиксом; если префикс присутствует, он возвращает остаток в одноэлементном списке (успех в монаде списка), в противном случае пустой список (ошибка в монаде списка)&
использует монаду списка для «недетерминированного» исполнения; Этоd
(словарное слово),!
для сопоставления формы Морзе этого слова (w>>=((…)!!).fromEnum
что эквивалентноconcatMap (((…)!!) . fromEnum) w
) с входной строкойi
,d&j
), чтобы соответствовать остальной части строки, иw:n
в монаде списка[w:n]
(которая является более коротким, конкретным эквивалентомreturn (w:n)
).Обратите внимание, что каждая строка после строки 6 является частью
do
выражения, начинающегося со строки 6; это занимает ровно столько же символов, что и точки с запятой в одной строке, но более читабельно, хотя вы можете сделать это только один раз в программе.Эта программа очень медленная. Это можно сделать быстрее (и немного дольше) легко, сохраняя сокращенные слова рядом с оригиналами в списке, а не пересчитывая их при каждом совпадении с образцом. Следующее, что нужно сделать, - это сохранить слова в бинарном дереве, снабженном символами Морзе (2-кратная последовательность ), чтобы избежать попыток ненужных ветвей.
Это можно сделать немного короче, если файл словаря не содержит неиспользуемые символы, такие как «-», что позволяет удалить
replicate 97"X"++
в пользу выполнения.(-97+)
перед!!
.источник
(+(-97))
можно переписать как(-97+)
?|0<1=[]
ко второму определениюinteract
и выиграйте 12 символов.interact$unlines.map unwords.(words f&)
concatMap
на>>=
Питон -
363345Код:
Объяснение:
Словарь должен храниться в виде простого текстового файла с именем "d".
D
,P
,U
ИN
только некоторые вспомогательные переменные для более короткого определения таблицы Морзе поиска.s(i)
является рекурсивной функцией, которая печатает ранее переведенную часть сообщенияp
и каждый действительный перевод оставшейся части кодаi
: еслиi
пусто, мы достигли конца кода, иb
содержит весь перевод, таким образом, мы простоprint
его. В противном случае мы проверяем каждое словоw
в словареd
, переводим его в азбуку МорзеC
и, если оставшийся кодi
начинается сC
, мы добавляем словоw
в переведенное началоb
иs
рекурсивно вызываем функцию для остатка.Примечание по эффективности:
Это довольно медленная, но играющая в гольф версия. Особенно загрузка словаря и построение таблицы поиска Морзе (
dict(zip(...))
) в каждой итерации (чтобы избежать большего количества переменных) стоит дорого. И было бы более эффективно переводить все слова в файле словаря заранее, а не в каждой рекурсии по требованию. Эти идеи приводят к следующей версии, содержащей еще 40 символов, но значительно ускоренной:источник
.startswith(C)
на[:len(C)]==C
.d=sorted(open('d').read().split(),key=len,reverse=1)
Или сделайте это внешне, предварительно отсортировав ваш словарь таким образом.M=eval(open('d').read())
:)Perl (5.10+), 293 символа
Файл словаря должен быть сохранен как «d» (и должен быть в формате unix, если вы не хотите CR между словами), ввод Морзе на stdin, без завершающей строки (используйте
echo -n
).(переносы строк только для форматирования).
Ungolfed код:
Модус Операнди:
Символы азбуки Морзе сохраняются путем изменения "." и «-» в двоичные цифры 0 и 1, добавляя «1» (так что начальные точки не сожрались), преобразовывая двоичное число в десятичное, а затем кодируя символ со значением 61 выше (что дает мне все печатные символы и ничего, что не требует обратной косой черты).
Я подумал об этом как о проблеме разделения и создал решение, основанное на этом. Для каждого слова в словаре он создает объект регулярного выражения, который будет сопоставлять (и захватывать) представление без пробела этого слова в начале строки. Затем он начинает поиск в ширину, создавая состояние, которое не соответствует ни одному слову и имеет весь ввод в качестве «оставшегося ввода». Затем он расширяет каждое состояние, ища слова, которые совпадают в начале оставшегося ввода, и создает новые состояния, которые добавляют слово к подобранным словам и удаляют морзе из оставшегося ввода. Состояния, которые не имеют оставшихся входных данных, являются успешными и имеют напечатанный список слов. Состояния, которые не могут соответствовать ни одному слову (включая успешные), не генерируют дочерние состояния.
Обратите внимание, что в негольфированной версии состояния являются хэшами для удобства чтения; в версии для гольфа они являются массивами (для более короткого кода и меньшего потребления памяти); Слот
[0]
- это оставшиеся входные данные, а слот[1]
- это совпадающие слова.Комментарий
Это безбожно медленно. Мне интересно, есть ли решение, которого нет. Я попытался построить один с использованием Marpa (парсер Earley с возможностью давать несколько разборов для одной входной строки), но мне не хватило памяти только для построения грамматики. Возможно, если бы я использовал низкоуровневый API вместо ввода BNF ...
источник
chomp()
. Нужно ли мне?ord
вместоord$_
. Бритье, говоря 1 байтjoin$"
вместоjoin" "
Хаскелл - 418
Эта проблема декорирования может быть эффективно решена путем динамического программирования. Я знаю, что это Codegolf, но я люблю быстрый код.
Скажем, у нас есть входная строка
s
, затем мы строим массивdp
,dp[i]
это список всех допустимых результатов декодирования подстрокиs[:i]
. Для каждого словаw
в словаре сначала мы его кодируемmw
, а затем можем вычислить частьdp[i]
изdp[i - length(mw)]
ifs[i - length(mw):i] == mw
. Временная сложность строительстваdp
составляетO({count of words} {length of s} {max word length})
. Наконец,dp[length(s)]
последний элемент - это то, что нам нужно.На самом деле нам не нужно хранить полное декодирование как элемент каждого
dp[i]
. Нам нужно последнее расшифрованное слово. Это делает реализацию намного быстрее. Чтобы завершить дело «Привет, мир» на моем ноутбуке i3, понадобилось менее 2 секунд. Для других случаев, размещенных в вопросе, программа не завершится практически, так как их слишком много для вывода.Используя технику динамического программирования, мы можем вычислить количество допустимых декодирований . Вы можете найти код здесь . Полученные результаты:
Ungolfed
Golfed
источник
PHP,
234226 байтрекурсивная функция, берет словарь из файла с именем
d
.Сбой для каждого слова в словаре, содержащего не букву.
Вы можете использовать любое имя файла, если вы
define ("d","<filename>");
перед вызовом функции.Добавьте 2 или 3 байта для более быстрого выполнения:
Удалить
$s?:print"$r\n";
, вставить$s!=$m?
до0!==
и:print$r.$w
перед;}}
.сломать
источник
Groovy
377337Заметки
Диктовкой должен быть файл с именем
d
. Строка Морзе передается из командной строки. например:Для "сжатия кода Морзе" я использую двоичное дерево
источник