Цель этой задачи - написать программу, способную угадать слово за наименьшее количество попыток. Он основан на концепции телешоу Lingo ( http://en.wikipedia.org/wiki/Lingo_(US_game_show) ).
правила
Учитывая длину слова, переданного в качестве первого аргумента в командной строке, программа проигрывателя имеет пять попыток угадать слово, записав предположение на его стандартный вывод, за которым следует один \n
символ.
После предположения программа получает на свой стандартный ввод строку, за которой также следует один \n
символ.
Строка имеет ту же длину, что и слово для угадывания, и состоит из последовательности следующих символов:
X
: это означает, что данная буква отсутствует в слове угадать?
: это означает, что данная буква присутствует в слове угадать, но в другом местеO
: это означает, что письмо в этом месте было правильно угадано
Например, если слово угадать есть dents
, а программа отправляет слово dozes
, оно получит, OXX?O
потому что d
и s
правильно, e
неуместно, а так o
и z
нет.
Будьте внимательны, если буква присутствует в попытке угадать больше раз, чем в слове для угадывания, она не будет помечена как ?
и O
более раз, чем количество вхождений буквы в слове для угадывания. Например, если слово «угадать» есть, cozies
и программа отправляет tosses
, оно получит, XOXXOO
потому что есть только одно, s
чтобы найти.
Слова выбираются из списка английских слов. Если слово, отправленное программой, не является допустимым словом правильной длины, попытка считается автоматической неудачей, и X
возвращаются только слова.
Программа проигрывателя должна предполагать, что файл с именем wordlist.txt
и содержащим одно слово в строке присутствует в текущем рабочем каталоге и может быть прочитан при необходимости.
Предположения должны состоять только из буквенных букв нижнего регистра ( [a-z]
).
Другие сетевые или файловые операции для программы запрещены.
Игра заканчивается, когда O
возвращается строка, состоящая только из или после того, как программа сделала 5 попыток и не смогла угадать слово.
счет
Счет игры определяется по формуле:
score = 100 * (6 - number_of_attempts)
Так что, если слово правильно угадано с первой попытки, дается 500 очков. Последняя попытка стоит 100 очков.
Неспособность угадать слово дает ноль очков.
Яма
Программы игроков будут оцениваться путем попытки угадать 100 случайных слов для каждой длины слова от 4 до 13 символов включительно.
Случайный выбор слов будет сделан заранее, поэтому все записи должны будут угадывать одни и те же слова.
Победившая программа и принятый ответ будут теми, кто наберет наибольшее количество очков.
Программы будут запускаться на виртуальной машине Ubuntu с использованием кода по адресу https://github.com/noirotm/lingo . Реализации на любом языке принимаются до тех пор, пока предоставляются разумные инструкции по их компиляции и / или запуску.
Я предоставляю несколько тестовых реализаций в ruby в репозитории git, не стесняйтесь черпать вдохновение из них.
Этот вопрос будет периодически обновляться с рейтингом опубликованных ответов, чтобы претенденты могли улучшить свои записи.
Официальная итоговая оценка состоится 1 июля .
Обновить
Записи теперь могут предполагать наличие wordlistN.txt
файлов для ускорения чтения списка слов для текущей длины слова для N от 4 до 13 включительно.
Например, есть wordlist4.txt
файл, содержащий все четырехбуквенные слова, wordlist10.txt
содержащий все десятибуквенные слова и т. Д.
Результаты первого тура
На дату 2014-07-01 было подано три заявки со следующими результатами:
4 5 6 7 8 9 10 11 12 13 Total
./chinese-perl-goth.pl 8100 12400 15700 19100 22100 25800 27900 30600 31300 33600 226600
java Lingo 10600 14600 19500 22200 25500 28100 29000 31600 32700 33500 247300
./edc65 10900 15800 22300 24300 27200 29600 31300 33900 33400 33900 262600
** Rankings **
1: ./edc65 (262600)
2: java Lingo (247300)
3: ./chinese-perl-goth.pl (226600)
Все записи выполнялись последовательно, с явным победителем, являясь записью @ edc65 для C ++.
Все участники довольно классные. До сих пор я не мог даже победить @ Chinese-Perl-Goth.
Если будет представлено больше записей, будет проведена другая оценка. Текущие записи также могут быть улучшены, если вы чувствуете, что можете сделать лучше.
источник
Ответы:
C ++ 267700 Баллов
Портирование со старого движка MasterMind.
Отличия от MasterMind:
Основная идея заключается в выборе слова, которое минимизирует пространство решения. Алгоритм действительно медленный для первого предположения (я имею в виду «дни»), но лучшее первое предположение зависит только от слова len, поэтому он жестко закодирован в источнике. Другие догадки делаются за считанные секунды.
Код
(Скомпилировать с g ++ -O3)
Мои оценки
Оценка на жаргоне, 100 раундов:
Всего 265'100
Самооценка баллов
Вот мои средние баллы, набранные по всему списку слов. Не вполне достоверно, потому что некоторые детали алгоритма изменились во время тестов.
Согласно этим числам, мой средний балл должен быть около 257'800
PIT SCORE
Наконец я установил Ruby, так что теперь у меня есть «официальный» результат:
источник
Java, 249700 баллов (в моем тесте лучше китайского Perl Goth)
Обновлен рейтинг:
Вот старый список с использованием рейтинга
pit.rb
:По сравнению с @chineseperlgoth я проигрываю более короткими словами (<6 символов), но выигрываю более длинными словами (> = 6 символов).Идея похожа на @chineseperlgoth, просто моя основная идея состоит в том, чтобы найти предположение (может быть любым словом той же длины, не обязательно одной из оставшихся возможностей), которое дает больше информации для следующего предположения.
В настоящее время я все еще играю с формулой, но для табло выше я выбираю слово, которое даст минимум для:В последней версии используется другая оценка, чтобы найти следующую лучшую догадку, которая максимизирует число «единичных возможностей» после текущей догадки. Это делается путем опробования всех слов в сокращенном списке слов (чтобы сэкономить время) на всех возможных кандидатах, и посмотреть, какое предположение более вероятно, чтобы произвести «единственную возможность» (то есть, после этого предположения будет только один возможный ответ) для Следующее предположение.
Так, например, этот прогон:
Из первых трех догадок мы уже получили «* oo * s» где-то с «n», и нам все еще нужно выяснить еще одну букву. Теперь прелесть этого алгоритма в том, что вместо того, чтобы угадывать слова, похожие на эту форму, он вместо этого угадывает слово, которое вообще не имеет отношения к предыдущим догадкам, пытаясь дать больше букв, надеясь выявить пропущенную букву. В этом случае случается также получить правильную позицию для пропущенного «b» и завершает с правильным окончательным предположением «благ».
Вот код:
источник
Perl
Есть еще место для улучшений, но, по крайней мере, это лучше, чем в примере игроков :)
Предполагает доступ для записи в текущий каталог для кэширования списков слов (чтобы он работал немного быстрее); создаст
wordlist.lenN.stor
файлы используяStorable
. Если это проблема, удалитеread_cached_wordlist
и измените код, чтобы использовать толькоread_wordlist
.объяснение
Сначала я строю гистограмму частот букв во всех словах в текущем списке слов (
build_histogram
). Затем мне нужно выбрать мою следующую догадку - что сделаноfind_best_word
. Алгоритм оценки просто складывает значения гистограммы вместе, пропуская уже увиденные буквы. Это дает мне слово, содержащее наиболее часто встречающиеся буквы в списке слов. Если есть более одного слова с данным счетом, я выбираю одно случайно. Найдя слово, я отправляю его на игровой движок, читаю ответ и пытаюсь сделать с ним что-нибудь полезное :)Я поддерживаю набор условий, то есть букв, которые могут встречаться в определенной позиции в слове. На старте это просто
(['a'..'z'] x $len)
, но обновляется на основе подсказок, приведенных в ответе (см.update_conds
). Затем я строю регулярное выражение из этих условий и фильтрую список слов через него.Во время тестов я обнаружил, что вышеупомянутая фильтрация не
?
очень хорошо справляется с s, следовательно, второй фильтр (filter_wordlist_by_reply
). Это использует тот факт, что письмо, помеченное как?
слово, встречается в слове в другой позиции, и соответственно фильтрует список слов.Эти шаги повторяются для каждой итерации основного цикла, если только решение не найдено (или невозможно больше читать из stdin, что означает сбой).
Код
источник