Мне было интересно увидеть ответы на этот (ныне несуществующий) вопрос , но он никогда не был исправлен / улучшен.
Учитывая набор шестигранных кубиков Боггл (конфигурация, украденная из этого вопроса ), определите за две минуты времени обработки, какая конфигурация платы позволит получить максимально возможную оценку. (то есть, в какой кости, в каком месте, с какой стороной вверх можно получить наибольшее количество слов для подсчета очков?)
ЗАДАЧА
Ваш код должен работать не более 2 минут (120 секунд). В это время он должен автоматически прекратить работу и распечатать результаты.
Итоговым результатом соревнования будет средний балл 5 баллов программы.
- В случае ничьей победителем будет тот алгоритм, который найдет больше слов.
- В случае ничьей, победителем будет тот алгоритм, который найдет более длинные (8+) слов.
ПРАВИЛА / ТРУДНОСТИ
Это проблема кода; длина кода не имеет значения.
Пожалуйста, обратитесь к этой ссылке для списка слов (используйте
ISPELL "english.0"
список - в списке SCOWL отсутствуют некоторые довольно распространенные слова).- На этот список можно ссылаться / импортировать / читать в вашем коде любым удобным для вас способом.
- Только слова, соответствующие регулярному выражению
^([a-pr-z]|qu){3,16}$
Будут засчитаны . (Только строчные буквы, 3-16 символов, qu должны использоваться как единое целое.)
Слова формируются путем связывания смежных букв (горизонтальных, вертикальных и диагональных) для написания слов в правильном порядке, без использования одного кубика более одного раза в одном слове.
- Слова должны состоять из 3 букв или более; короткие слова не принесут очков.
- Дублированные буквы допустимы, только не кубики.
- Слова, которые охватывают края / пересекаются с одной стороны доски на другую, не допускаются.
Окончательная оценка Boggle ( не вызов ) представляет собой сумму баллов по всем найденным словам.
- Значение точки, назначаемое для каждого слова, зависит от длины слова. (см. ниже)
- Обычные правила Boggle вычитают / сбрасывают слова, найденные другим игроком. Предположим, что здесь не участвуют другие игроки, и все найденные слова учитываются в общем балле.
- Однако слова, найденные более одного раза в одной и той же сетке, должны учитываться только один раз.
Ваша функция / программа должна НАЙТИ оптимальное расположение; просто жесткое кодирование заранее определенного списка не сработает.
Ваш вывод должен быть сеткой 4x4 вашей идеальной игровой доски, списком всех найденных слов для этой доски и баллом Boggle, чтобы соответствовать этим словам.
УМИРАТЬ КОНФИГУРАЦИЮ
A A E E G N
E L R T T Y
A O O T T W
A B B J O O
E H R T V W
C I M O T U
D I S T T Y
E I O S S T
D E L R V Y
A C H O P S
H I M N Qu U
E E I N S U
E E G H N W
A F F K P S
H L N N R Z
D E I L R X
СТАНДАРТНЫЙ СТОЛ СЧЕТЧИКОВ
Word length => Points
<= 2 - 0 pts
3 - 1
4 - 1
5 - 2
6 - 3
7 - 5
>= 8 - 11 pts
*Words using the "Qu" die will count the full 2 letters for their word, not just the 1 die.
ПРИМЕР ВЫХОДА
A L O J
V U T S
L C H E
G K R X
CUT
THE
LUCK
HEX
....
140 points
Если требуется дальнейшее уточнение, пожалуйста, спросите!
источник
4527
(1414
всего слов), найдена здесь: ai.stanford.edu/~chuongdo/boggle/index.html^([a-pr-z]|qu){3,16}$
(которое неправильно исключало бы трехбуквенные слова с помощью qu, но их нет).Ответы:
С, в среднем
500+15001750 балловЭто относительно небольшое улучшение по сравнению с версией 2 (см. Примечания к предыдущим версиям ниже). Есть две части. Во-первых: вместо случайного выбора досок из пула, программа теперь выполняет итерации по каждой доске в пуле, используя каждую из них по очереди, прежде чем вернуться к вершине пула и повторить. (Так как пул изменяется во время этой итерации, все еще будут платы, которые выбираются дважды подряд, или хуже, но это не представляет серьезной проблемы.) Второе изменение заключается в том, что программа теперь отслеживает изменения пула и если программа выполняется слишком долго, не улучшая содержимое пула, она определяет, что поиск "остановился", очищает пул и начинает заново с новым поиском. Он продолжает делать это, пока две минуты не истекут.
Сначала я думал, что буду использовать какой-то эвристический поиск, чтобы выйти за пределы диапазона в 1500 пунктов. Комментарий @ mellamokb о доске из 4527 пунктов заставил меня предположить, что есть много возможностей для улучшения. Однако мы используем сравнительно небольшой список слов. Доска из 4527 баллов набирала баллы с использованием YAWL, который является самым всеобъемлющим из всех списков слов - он даже больше, чем официальный список слов США Scrabble. Имея это в виду, я повторно проверил платы, которые обнаружила моя программа, и заметил, что существует ограниченный набор плат выше 1700 или около того. Так, например, у меня было несколько прогонов, в которых была обнаружена доска, набравшая 1726 очков, но это всегда была та же самая доска, которая была найдена (игнорируя повороты и отражения).
В качестве еще одного теста я запустил свою программу, используя YAWL в качестве словаря, и он нашел доску из 4527 баллов после примерно десятка запусков. Учитывая это, я предполагаю, что моя программа уже находится на верхнем пределе пространства поиска, и, следовательно, переписывание, которое я планировал, внесло бы дополнительную сложность при очень небольшом выигрыше.
Вот мой список пяти досок с наибольшим количеством очков, которые моя программа нашла, используя список
english.0
слов:Я считаю, что «доска объявлений grep» 1772 года (как я ее назвал), состоящая из 531 слова, является самой высокой оценочной доской, возможной для этого списка слов. Более 50% двухминутных прогонов моей программы заканчиваются на этой доске. Я также оставил свою программу работающей на ночь, но не нашел ничего лучшего. Так что, если есть доска с более высоким баллом, она, вероятно, должна иметь какой-то аспект, который побеждает технику поиска программы. Например, моя программа никогда не сможет обнаружить доску, на которой каждое возможное небольшое изменение макета приводит к значительному снижению общего балла. Я догадываюсь, что такая доска вряд ли существует.
Примечания к версии 2 (9 июня)
Вот один из способов использовать начальную версию моего кода в качестве отправной точки. Изменения в этой версии состоят из менее чем 100 строк, но в три раза увеличивают средний игровой счет.
В этой версии программа поддерживает «пул» кандидатов, состоящий из N досок с наибольшим количеством очков, которые программа сгенерировала до сих пор. Каждый раз, когда генерируется новая доска, она добавляется в пул, а доска с наименьшим количеством очков в пуле удаляется (что вполне может быть только что добавленной доской, если ее оценка ниже, чем у того, что уже есть). Изначально пул заполняется случайно сгенерированными досками, после чего он сохраняет постоянный размер на протяжении всего выполнения программы.
Основной цикл программы состоит в том, чтобы выбрать случайную доску из пула и изменить ее, определить счет этой новой доски и затем поместить ее в пул (если она набирает достаточно хорошие оценки). Таким образом, программа постоянно совершенствует доски с высокими баллами. Основным действием является постепенное, поэтапное улучшение, но размер пула также позволяет программе находить многоэтапные улучшения, которые временно ухудшают счет доски, прежде чем она улучшится.
Как правило, эта программа довольно быстро находит хороший локальный максимум, после которого, по-видимому, любой лучший максимум находится слишком далеко, чтобы его можно было найти. И опять же, нет смысла запускать программу дольше 10 секунд. Это может быть улучшено, например, если программа обнаружит эту ситуацию и начнет новый поиск с новым пулом кандидатов. Однако это приведет лишь к незначительному увеличению. Правильная техника эвристического поиска, вероятно, будет лучшим способом исследования.
(Примечание: я видел, что эта версия генерирует около 5 тыс. Досок в секунду. Поскольку первая версия обычно производила 20 тыс. Досок в секунду, я был изначально обеспокоен. Однако после профилирования я обнаружил, что на управление списком слов было потрачено дополнительное время. Другими словами, это было полностью связано с тем, что программа находила намного больше слов на доске. В свете этого я рассмотрел вопрос об изменении кода для управления списком слов, но, учитывая, что эта программа использует только 10 из отведенных ей 120 секунд, например, оптимизация была бы очень преждевременной.)
Примечания к версии 1 (2 июня)
Это очень, очень простое решение. Все, что он делает, это генерирует случайные доски, а затем через 10 секунд выводит ту, которая набрала наибольшее количество очков. (Я установил значение по умолчанию на 10 секунд, потому что дополнительные 110 секунд, разрешенные спецификацией проблемы, как правило, не улучшают окончательное решение, найденное достаточно, чтобы его стоило ждать.) Так что это чрезвычайно глупо. Тем не менее, он обладает всей инфраструктурой, чтобы стать хорошей отправной точкой для более интеллектуального поиска, и если кто-то захочет использовать его до истечения срока, я призываю его сделать это.
Программа начинается с чтения словаря в древовидную структуру. (Форма не настолько оптимизирована, как могла бы быть, но она более чем хороша для этих целей.) После некоторой другой базовой инициализации она затем начинает генерировать платы и оценивать их. Программа проверяет около 20 тысяч досок в секунду на моей машине, и после примерно 200 тысяч досок случайный подход начинает иссякать.
Поскольку в каждый момент времени оценивается только одна доска, данные оценки сохраняются в глобальных переменных. Это позволяет мне минимизировать количество постоянных данных, которые должны передаваться в качестве аргументов рекурсивным функциям. (Я уверен, что это даст некоторым людям ульи, и им я приношу свои извинения.) Список слов хранится в виде двоичного дерева поиска. Каждое найденное слово должно быть найдено в списке слов, чтобы повторяющиеся слова не учитывались дважды. Однако список слов необходим только во время процесса эвакуации, поэтому он отбрасывается после того, как результат будет найден. Таким образом, в конце программы выбранная доска должна быть оценена заново, чтобы можно было распечатать список слов.
Забавный факт: средний балл за случайно сгенерированную доску Boggle, по
english.0
оценкам, составляет 61,7 балла.источник
VBA (в среднем в настоящее время в диапазоне 80-110 баллов, незакончено)
Вот мой рабочий процесс, но он далеко не самый лучший; мой абсолютный лучший результат на любой доске после многих тестовых прогонов составляет около 120. По-прежнему требуется лучшая общая очистка, и я уверен, что в ряде мест можно добиться большей эффективности.
Это, наверное, выглядит ужасно для некоторых из вас, но, как я уже сказал, WIP. Я очень открыт для конструктивной критики! Извините за очень длинное тело ...
Модуль класса игры в кости :
Модуль класса дерева :
Модуль класса TreeNode :
Основной модуль :
источник
Быстрый взгляд на размер пространства поиска.
Уменьшение, чтобы исключить повторение на каждом кубике.
@breadbox сохраняет словарь как проверку хеш-таблицы O (1).
РЕДАКТИРОВАТЬ
Лучший совет (я был свидетелем до сих пор)
источник
Моя запись здесь на Dream.In.Code ~ 30 мс при поиске на плате (на 2-ядерном компьютере должна быть быстрее с большим количеством ядер)
источник
:
инhttp://
. ;-).NET
чтобыVBA
не слишком сложно.