Как будто этот вызов может быть больше Pythonesque по духу ... Никаких предварительных знаний о цепях Маркова или методах шифрования не требуется.
Вы - шпион, которому необходимо получить важную информацию от британской службы безопасности M1S. Агенты M1S хорошо знают, что их сигналы Wi-Fi могут быть перехвачены, их уязвимости безопасности в Android / iOS эксплуатируются и т. Д., Поэтому все они используют Nokia 3310 для передачи текстовой информации, которая набирается с помощью автозаполнения T9 .
Ранее вы взламывали телефоны для доставки в спецслужбу и устанавливали клавиатурные шпионы под их великолепными пластиковыми клавиатурами, так что теперь вы получаете последовательности чисел, соответствующие набранным буквам, так что « орел покинул гнездо, предупреждая агентов » становится
84303245304270533808430637802537808430243687
Но ждать! Некоторые последовательности Т9 неоднозначны («6263» может быть «имя», «грива» или «гобой»; чем более неясным, тем более подозрительным он становится!), Что вы делаете? Вы знаете, что единственным вступительным экзаменом, который использует M1S, является подведение итогов шедевра Марселя Пруста «Воспоминание о прошлом» за 15 секунд, поэтому вы хотите выбрать слово, следующее за предыдущим, в соответствии с его частотным распределением во всем chef-d ' Увр из Пруста!
Можете ли вы взломать код и получить то, что может быть оригинальным сообщением?
Принцип Т9
Механизм автозаполнения T9 может быть описан следующим образом. Он отображает буквенные символы на цифры, как показано на рисунке выше.
abc -> 2
def -> 3
ghi -> 4
jkl -> 5
mno -> 6
pqrs -> 7
tuv -> 8
wxyz -> 9
<space> -> 0
<other> -> <is deleted>
Расшифровщик T9 получает последовательность цифр и пытается угадать слово, которое можно набрать с помощью этих клавиш. Он может использовать стандартную таблицу частот, но мы идем на один шаг дальше и предсказываем следующее слово, используя цепочку Маркова!
Образец обучения
Корпус является это сильно раздела версию «Воспоминания о прошлом» Пруст ( s/-/ /g
, s/['’]s //g
и s/[^a-zA-Z ]//g
- убираться в заблуждении притяжательным 's
!) Первоначально опубликовано на Университете Аделаиды сайта (текст этой работы находится в общественном достоянии в Австралии).
Весь текст должен быть проанализирован как одна строка, как одно длинное предложение, как один длинный вектор слов (в зависимости от того, что более удобно для вашего языка), лишен разрывов строк и разбит на слова в пробелах . (Я не предоставляю файл с одним абзацем, потому что такие инструменты могут быть недовольны инструментами github.)
Как прочитать весь текст одной строкой / предложением? Пример в R :
p_raw <- read.table("proust.txt", sep="\t") # Because there are no tabs
p_vec <- as.character(p_raw$V1) # Conversion to character vector
p_str <- paste(p_vec, collapse=" ") # One long string with spaces
p_spl <- strsplit(p_str, split=" ")[[1]] # Vector of 1360883 words
proust <- p_spl[p_spl!=""] # Remove empty entries — 1360797
задача
Учитывая последовательность цифр как число, верните возможную текстовую строку, которую можно набрать, используя соответствующие клавиши T9, используя цепочку вероятностей, чтобы предсказать следующее слово X на основе этого обучающего текста, рассматриваемого как одно длинное предложение.
Если X является первым T9-словом в тексте и существует несколько догадок, выберите одно из них случайным образом, в противном случае выберите единственное возможное.
Для всех последующих T9-слов X (i), которым предшествует слово, уже расшифрованное w (i-1) :
- Если слово T9 X можно преобразовать в обычное слово x одним уникальным способом, сделайте это.
- Если для X доступно несколько вариантов преобразования , скажем, x1, x2, ... , найдите предыдущее угаданное слово w .
- Если за w никогда не следует ничего, что отображается в X в оригинальной работе Пруста, выберите любой из возможных x1, x2, ... наугад.
- Если w X всегда соответствует w x1 в оригинале и нет одновременных xi , которые можно было бы отобразить в X , выберите x1 .
- Если w X можно преобразовать в w x1 , w x2 , ..., которые можно найти в корпусе, подсчитайте все возможные xi , следующие за w, и сопоставьте их с X в корпусе и выберите xi с вероятностью xi / (x1 + х2 + ...) .
Пример 2а. Если сообщение есть 76630489
, где 489
может быть guy
или ivy
(они встречаются в корпусе хотя бы один раз), 7663
его можно расшифровать как some
(очень вероятное первое слово). Если за some
ним никогда не следует ничего, что отображается 489
в корпусе, то выбирайте guy
или ivy
случайным образом с вероятностью 0,5.
Пример 2б. Если сообщение есть 766302277437
, где 2277437
может быть barrier
или carrier
, 7663
может быть расшифровано как some
. Если Пруст всегда использовал some carrier
и никогда some barrier
, тогда выбирай some carrier
.
Пример 2с. Предположим, что вы хотите расшифровать последовательность 536307663
. 5363
было предсказано как lend
. 7663
может быть любой из них: pond
, roof
и some
. Вы подсчитываете вхождения слова, следующего lend
за образцом в корпусе. Предположим, вы получили что-то вроде этого (просто для иллюстрации):
T9 Word following lend Occurrences
7663 some 7
7663 pond 2
7663 roof 1
Так что если 7663
ему предшествует lend
, есть 7/(7+2+1)=70%
вероятность, что 7663
означает some
, 20% pond
и 10% roof
. Ваш алгоритм должен выдавать lend some
в 70% случаев, lend pond
в 20% случаев и т. Д.
Вы можете смело предполагать, что агенты используют только буквы и пробелы z (без знаков препинания, без притяжений 's
и без цифр).
Вы также можете предположить, что агенты M1S никогда не используют какие-либо слова, выходящие за рамки «Воспоминания о прошлом» (это колоссальный словарь из 29 237 слов!).
Функциональность T9 была реализована в этой задаче , так что вы можете взглянуть на нее.
Если вам нужна помощь, вероятностные цепочки были великолепно приручены в этой , той и следующих задачах, но вам даже не нужно знать принцип таких цепочек: все указано в задании.
Контрольные примеры
--Inputs--
20784250276960369
20784250276960369
84303245304270533808430637802537808430243687
94280343084306289072908608430262780482737
94280343084306289072908608430262780482737
--Possible outputs--
c quick brown fox
a stick crown fox
the eagle gas left the nest blest vie agents
what did the navy pay to the coast guards
what did the navy raz un the coast guards
Правила:
- Применяются стандартные лазейки .
- Вы не знаете исходное сообщение, все, что вы получаете, это последовательность цифр и файл proust.txt, который вам просто нужно загрузить в память / рабочую область / что угодно. Нет необходимости иметь что-то автономное; Предположим
proust.txt
, всегда доступно. - Ваш алгоритм должен иметь возможность создавать различные выходные данные с соответствующими вероятностями, если в соответствии с корпусом возможно более одного варианта дешифрования (см. Пример 2c).
Вам нужно быть максимально осторожным, поэтому выигрывает самый короткий код!
PS Очевидное преимущество этого вероятностного алгоритма состоит в том, что вероятность того, что вы получите истинную исходную строку для неоднозначной расшифрованной строки, стремится к одному - просто подождите ...
PPS См. Также Прогноз по частичному сопоставлению .
источник
Ответы:
R решение, неконкурентная иллюстрация того, что можно сделать
Сначала мы загружаем последовательность слов в память:
Во-вторых, нам нужна функция, которая обрабатывает любой текст:
Тогда мы Т9-ифы Пруст:
Окончательная подготовка: мы разбиваем входную строку на нули, используя функцию, которую мы вызываем
prep
):А теперь я предлагаю функцию, которая принимает любую входную строку чисел,
prep
s это и расшифровывает слова одно за другим:А теперь, что он на самом деле делает:
Второй пример:
Пожалуйста, не комментируйте, что это можно сыграть в гольф. Кажется, мало кто интересуется этой проблемой из-за моего ужасного многословия, поэтому я опубликовал этот ответ, чтобы показать, как может выглядеть возможная программа. Вам не нужно повышать / понижать этот ответ.
источник
Python 3, 316 байт
источник