Это последний спринт ... и половина вашей команды заболела. Вы работаете поздно, просто делаете свой последний коммит в течение дня, с нетерпением ожидая ... почему выключили свет? Я не помню, чтобы охранник приходил ... о, нет! Я оставил свои ключи дома!
По мере того, как весь ужас ситуации погружается, вы решаете, что вы собираетесь сбежать .
Резюме задачи
Чтобы осуществить побег, вам нужен план! Однако вы знаете, что любой план может потерпеть неудачу, и разные планы требуют разных усилий.
Будучи голодным, уставшим и инженером, вы решаете написать короткую программу, чтобы определить наилучший способ выхода из комплекса, уравновешивая проблемы вероятности успеха и усилий, которые для этого потребуются.
Вы делаете карту здания:
#######################
# = #
! = ! <-- window
# ! = # (freedom!)
#################= #
# # = #
# # = #
# # = #
# o ! # # ! = #
##| ! ## # ! = #
#######################
^ ^ ^
me my door ludicrously high shelves
(locked) (climbable)
Чтобы сбежать из офиса, вам придется убраться с карты. Здесь вы видите 2 окна ( !
), каждое из которых приведет вас к свободе, но доступно только одно из них. Мы определяем «вне карты» как то, что ваши ноги находятся за пределами карты
Типы клеток
- empty, you can be here (i.e. the escapee can consume this cell)
# - solid (your desk, your in-tray), you can't be here, but you can stand on it
! - destructible, (co-worker's desk, door, window), you can't be here until you smash it first (turning it into an empty cell)
= - climbable, (fire ladder, filing cabinet, etc.), you can be here
Клетки, первоначально использованные беглецом, считаются пустыми.
Технические характеристики действий
У вас есть ряд возможных действий в вашем распоряжении. Они определяются простыми переходами состояний с некоторой целочисленной вероятностью успеха. Например, при ходьбе вы перемещаете беглеца на одну ячейку, которую мы представляем следующим переходом:
шаг
1 ст, 100%, зеркало
o. o
|. --> |
# #
Точки показывают ячейки, которые должны быть пустыми (или проходимыми, но не сплошными или разрушаемыми), потому что мы движемся в него или через него. 100% означает, что у вас есть 100% шанс не навредить себе и закончить свой дерзкий побег. Все вероятности будут целочисленными процентами между 1% и 100% включительно. Первая диаграмма показывает начальное состояние (стоя на чем-то твердом, стоя рядом с каким-то пустым пространством). Вторая диаграмма показывает состояние терминала (перенесено в пустое пространство). Нет никаких требований для каких-либо неуказанных ячеек (пробелов, ) слева (начальное состояние) быть чем-то конкретным. Неуказанные клетки (пробел,
) справа (состояние терминала) должно быть таким же, каким они были до этого (например, за тем, что было за беглецом, или за тем, на что я хожу (будь то пустое пространство или иным образом). Обратите внимание, что все справа (состояние терминала) ) диаграммы изменят только ячейки с разрушаемых на пустые, никаких других изменений не произойдет. «1 stp» означает, что это стоит 1 stp: мы определяем «stp» как количество энергии, необходимое для выполнения шага.
«зеркало» означает, что это действие имеет две формы. «Правое» действие показано, «левое» действие является точным зеркалом, например:
.o
.|
#
это зеркальная (левая) форма
o.
|.
#
Правое действие называется «Right» (например, «Step Right»). Левое действие называется «Left» (например, «Step Left»).
На этих диаграммах беглец показан
o
|
в положении стоя (2 шт.) и
%
когда приседает (1 единица в высоту). Клетки , которые должны быть твердыми или разрушаемые обозначены хэш, #
. Клетки, которые не должны быть твердыми или разрушаемыми, обозначены точкой .
. Клетки, которые должны быть разрушаемыми, обозначены ударом !
. Вновь созданное пустое пространство показано подчеркиванием _
.
x
является контрольной точкой, которая не перемещается (она не существует, нет ограничений на то, какой должна быть эта ячейка (например, пробел )).
Примечание: мы игнорируем проблему быстрого замедления, когда вы падаете на пол, и да, в этой игре вы можете совершать совершенно эпические прыжки на лестницы)
шаг
1 ст, 100%, зеркало
o. o
|. --> |
x# x#
Подняться
1 ст, 100%, зеркало
= =
o. --> o
|. |
x= x=
шарканье
3 ст, 100%, зеркало
%. %
x# --> x#
Карабкаться вверх
10 шт, 95%, зеркало
o. %
|# --> #
x# x#
Капля
0 стп, 100%
o
| --> o
x. x|
Drop (Стенд)
0 стп, 100%
% o
x. --> x|
Подняться
2 ст, 100%
= o
o --> |
x| x
пресмыкаться
2 ст, 100%
o
| --> %
x# x#
стенд
4 ст, 100%
. o
% --> |
x# x#
Прыжок в длину
4 ст, 95%, зеркало
o.. o
|.. --> |
x# x#
Длинный прыжок
7 шт, 75%, зеркало
o... o
|... --> |
x# x#
Высокий прыжок
12 шт, 90%, зеркало
.. o
o. --> |
|
x# x#
Положи свою спину в это!
20 шт, 80%, зеркало
o!. _o
|!. --> _|
x# x#
перфоратор
8 шт, 90%, зеркало
o! o_
| --> |
x# x#
Удар
8 шт, 85%, зеркало
o o
|! --> |_
x# x#
Печать
8 ст, 90%
o o
| --> |
x! x_
планы
План - это последовательность действий, определенных выше. Например:
Step Left
High Jump Left
Crouch
Shuffle Left
Shuffle Left
Stand
Long Jump Left
Put your back into it! Left
Step Left
Обратите внимание на включение капель. Правила должны быть установлены так, чтобы вы не делали ничего, кроме бросания, но вы все равно должны планировать это!
Любой план требует усилий, которые являются суммой усилий для каждого шага. Существует также вероятность успеха, которая является продуктом вероятности успеха каждого действия. Простой пример:
Step Right: 1stp, 100%
Long Jump Right: 7stp, 75%
Step Right: 1stp, 100%
Stamp: 8stp, 90%
Drop: 0stp, 100%
Drop: 0stp, 100%
Drop: 0stp, 100%
Drop: 0stp, 100%
Step Left: 1stp, 100%
Step Left: 1stp, 100%
High Jump Left: 12stp, 90%
Effort = 1+7+1+8+1+1+12 = 31
Success Probability = 75%*90*90% = 60.75%
«Рабочий пример» для карты в верхней части страницы можно найти как суть .
вход
Входные данные состоят из двух частей: целого числа и массива или строки символов.
Целое число - это минимально допустимая (процентная) вероятность успеха. Его следует интерпретировать как процент, поэтому 80 означает, что ваш план должен быть успешным с вероятностью не менее 80%.
Действительная карта - это прямоугольник, который включает стоящего беглеца (минимальный размер 1x2) и не содержит никаких неопределенных символов. Все строки будут одинаковой длины. Вы можете принять входные данные как одномерную строку с разделителями (разделитель должен быть одним непротиворечивым символом или одним из пары CRLF и LFCR), как аналогичный одномерный массив или двумерный массив. Если выбранный вами формат ввода не указывает каким-либо образом ширину или высоту карты, вы можете принять дополнительные аргументы для них (вы должны четко указать это в своем ответе). Вы можете смешивать аргументы командной строки и стандартный ввод, если он вам подходит (например, карта из stdin, минимальная вероятность успеха из argv). Ниже приведены примеры действительных и недействительных карт.
Действительно:
o
|
Действительно:
# #
! o #
! | #
#########
Неверно (нет беглеца):
# #
! #
! #
#########
Неверно (беглец всегда начинает стоять):
# #
! #
! % #
#########
Неверный (недопустимый символ):
# #
! ~ #
! #
#########
Неверно (не прямоугольник / строки разной длины):
# #
! o #
! | #
#########
Вы можете предположить, что ваш ввод действителен (мне все равно, что делает ваша программа, если ему передан неверный ввод).
Выход
Вывод текста (ASCII). Может быть возвращено в виде строки или напечатано на стандартный вывод. План должен быть ограничен LF, CRLF или LFCR. Точно так же после Обязательного Усилия должен быть другой LF, CRLF или LFCR. Трейлинг разрыв строки не является обязательным.
Вы должны вывести оптимальный план вместе с требуемым усилием или «Надежды нет!» если такого плана не существует. Вам не нужно выводить вероятность успеха. Этот текст может иметь или не иметь разрыв строки в конце.
Оптимальный план определяется как план (см. Выше), требующий минимальных усилий, по крайней мере, с заданной вероятностью успеха. Обратите внимание, что ваши вероятностные расчеты должны быть точными, вы не можете предполагать, что с плавающей запятой достаточно хорошо (поэтому я не ожидаю, что вы их выведете). Я постараюсь разработать контрольные примеры, чтобы честно проверить это (если вы их пройдете и не сделаете никаких ложных предположений, то вы можете считать, что ваше представление действительно).
Формат:
Required Effort: <effort>
<plan>
Например, для ввода
50
# #
! o #
! | #
#########
Соответствующий вывод будет:
Required Effort: 23
Step Left
Step Left
Step Left
Kick Left
Punch Left
Step Left
Step Left
Step Left
Step Left
Вероятность успеха здесь составляет 76,5%.
Для той же карты, но с минимальной вероятностью успеха в 80%, вам придется «положить в нее спину», что потребует больше усилий, но соответствует критерию вероятности успеха. Если минимальная вероятность успеха была больше 80%, вам нужно было бы подумать немного усерднее (пробить или ударить часть двери и вылезти наружу). Если бы минимальная вероятность успеха составляла 100%, вам пришлось бы распечатать «Надежды нет!»
Примеры
Возможно, что существует более одного действительного плана для ввода, ваш вывод не обязательно должен быть именно таким, но он должен иметь правильное требуемое усилие и быть действительным планом. Вы можете использовать верификатор для проверки ваших решений (см. Ниже)
Входные данные:
100
o
|
Выход:
Required Effort: 0
Drop
Входные данные:
5
# = #
# = !
# = ! ! !
# =#######
# = #
# = o #
# = ! | #
##########
Выход:
Required Effort: 57
Step Left
Kick Left
Step Left
Step Left
Step Left
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
High Jump Right
Long Jump Right
Step Right
Drop
Kick Right
Crouch
Shuffle Right
Shuffle Right
Входные данные:
60
#########
# ! # #
! ! ! o #
! # ! | #
#########
Выход:
Required Effort: 58
Step Left
Kick Left
Crouch
Shuffle Left
Shuffle Left
Stand
Punch Left
Clamber Up Left
Shuffle Left
Drop (Stand)
Kick Left
Crouch
Shuffle Left
Shuffle Left
Для той же карты, но 80%, результат должен быть:
There is no hope!
Для той же карты, но 50%, Требуемое усилие становится 56 с другим планом)
Входные данные:
50
#######################
# # = #
! # = !
# # = #
###### #####!## =### #
#= ## # = #
#=############# = #
#= = #
#= o = #
#!!| = #
#######################
Выход:
Required Effort: 121
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Step Right
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb Up
Climb off Right
Long Jump Left
Step Left
Step Left
Stamp
Drop
Drop
Crouch
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Shuffle Left
Stand
Clamber Up Left
Stand
Clamber Up Left
Stand
Step Left
Step Left
Step Left
Step Left
Punch Left
Clamber Up Left
Shuffle Left
Входные данные:
66
######
# ###
#o ! !
#| ! !
### ##
######
Выход:
Required Effort: 37
Step Right
Put your back into it! Right
Kick Right
Crouch
Shuffle Right
Shuffle Right
Входные данные:
Этот предназначен для проверки ряда ложных предположений, жертвой которых может стать, и, следовательно, может выглядеть немного странно
30
###################
# ## # # # # = #
! ## # # # = #
# # # = #
## ############= #
# ## # #= #
# = # #= #
! = # #= #
# = # #= #
#o= ! ==#
#|= ! =#
#!= # ==########==#
# # ! !! =#
# # !! ! = #
# # !!!!#########
# # # #
# # # #
###################
Выход с ограничением вероятности успеха 30:
Required Effort: 199
Long Jump Right
Put your back into it! Right
<snip>
Выход с ограничением шанса успеха 32:
Required Effort: 200
Long Jump Right
Punch Right
<snip>
Используя карту сверху в качестве входных данных с вероятностью успеха 1%, вы должны получить обязательное усилие 116 (шанс успеха ~ 32%, на выполнение моей тестовой программы ушло около 20 секунд).
Критерии Победы
Это код-гольф, пусть победит самый короткий код.
Чтобы иметь право, ваша функция или программа должны работать и иметь возможность решать каждый из приведенных выше тестовых случаев менее чем за 30 минут на приемлемой машине. Мой решатель делает их каждый менее чем за 30 секунд. Если тестовый сценарий (ниже) выполняется менее чем через 30 минут, вам, безусловно, хорошо.
Пример Solver, Verifier, Test Script и TestCases (с решениями)
Код C # для решателя и верификатора решения доступен здесь как гист . Суть также содержит file.txt
, который является машиночитаемой (достаточной) формой действий, описанных выше, и необходим для запуска программы. Любое расхождение между этим файлом и спецификацией не является преднамеренным.
Суть также содержит ряд тестовых случаев (включая все приведенные выше примеры) и сценарий PowerShell для автоматического запуска представления против них. Если скрипт сообщает вам, что определенный тест не пройден, вы можете запустить, OfficeEscapeSolver.exe testcase<n>.txt outputFromYourProgram.txt
чтобы увидеть больше деталей. Примеры решений для этих тестов приведены в другом Gist .
Весь код представляет собой полный беспорядок (хотя и не обманут), но вам не нужно уходить далеко от того, static void Main(...)
чтобы изменить количество выводимой информации (не стесняйтесь использовать эту информацию, я предоставил ее в вашу пользу!).
Прохождение тестового примера не обязательно означает, что ваш вывод правильно сформирован, так как скрипт и верификатор очень щедры. Ваш вывод должен соответствовать спецификации выше, чтобы ваше представление было действительным.
Если вы считаете, что нашли ошибку с решателем или тестовым сценарием, ошибкой в file.txt
или изворотливом тестовом сценарии , то, пожалуйста, прокомментируйте этот пост или иным образом пропишите мне в SE Chat; Я, вероятно, не замечу никаких других попыток общения.
Я не буду предоставлять тестовый скрипт в Bash или Batch, потому что я их не знаю, но я рад включить перевод и напишу версию C #, если люди захотят ее.
Post Amble
Есть вопросы? Не откладывайте, спросите их сегодня!
Задача состоит в том, чтобы потребовать усилий , дать серьезным игрокам в гольф что-то, во что они могут впиться.
Спасибо ais523 за отзыв о вводе / выводе.
Я могу предоставить больше тестовых примеров в файле gist, если люди хотят больше (не хотят, чтобы этот пост становился больше), или хотят предоставить некоторые свои собственные.
источник
Ответы:
Perl 5,
1425,1464,1481,1469,1485,1438 байт.Это было весело! И, шокирующе, похоже, что у меня самый короткий код до 1.5kB! :)
Я уверен, что наконец-то все заработало. Используемый разделитель есть
:
, и есть дополнительное заполнение двух строк сверху и одного столбца с каждой стороны. Итак, для вашего ввода:моя программа будет принимать: (NB: в конце должно быть двоеточие, но не в начале!)
Я использую регулярные выражения для перевода с одной карты на другую и решения с помощью грубой силы. Однако я не добавляю карты в список, если эта карта уже была достигнута с меньшими усилиями и большей или равной вероятностью. Карты удаляются из списка после исчерпания всех возможных перемещений с этой точки. Программа успешно завершается, когда она соответствует регулярному выражению, которое показывает, что я достиг боковой или нижней части, и заканчивается словами «Надежды нет!» когда список карт исчерпан.
К сожалению, была потрачена большая эффективность, чтобы убрать несколько байтов, поэтому игра в гольф довольно медленная;) Perl, похоже, считает, что уловки, в частности, довольно болезненны.
Без лишних слов,
Ради здравомыслия вот то же самое с символами новой строки и несколькими комментариями:
Я уже вижу пару мест, чтобы сократить еще несколько байтов, но я пока не хочу снова проходить все тестирование. Позже! :)
Изменить: Добавлены некоторые отступы ниже, чтобы более точно соответствовать вашему выводу при выходе через этаж. Удалены некоторые ошибки, поэтому код теперь может работать быстрее!
Изменить: не правильно обрабатывать лестницы и падения Все еще не совсем правильно разбирается в лестницах ... Попытка исправить это сейчас.
источник
C #
181414811395 байтЧто за наглость !! Я действительно очень доволен этим сейчас!
Попробуйте онлайн
Завершить программу, принимает ввод в STDIN, вывод в STDOUT. По сути, переписать мой оригинальный решатель, используя простой и неэффективно реализованный BFS, чтобы найти оптимальный путь. Это достаточно быстро, не может быть намного медленнее, чем моя другая реализация (хотя я на самом деле не рассчитал это время), безусловно, работает в установленные сроки. Большую часть стоимости составляет таблица действий, которая кодируется в виде отдельных значений запятых, в которых записывается имя, карта соответствия / совпадения и другие свойства каждого доступного действия.
Начинается с чтения с минимальной вероятностью успеха и карты. Затем он находит беглеца, удаляет его с карты и создает «состояние поиска», содержащее эту информацию. Затем он выполняет BFS, которая с минимальными усилиями повторно просматривает следующее состояние выполнения (гарантируя, что находит оптимальное решение). Прежде чем развернуть узел, он сравнивает свои усилия и вероятность успеха с предыдущими узлами с той же картой и местоположением спасателя и отклоняет себя, если уже найден лучший маршрут к этому состоянию. Если он переживет это, он добавит себя в «видимую» таблицу, чтобы впоследствии он мог отклонить состояние. Это все для производительности, и без этого фактор ветвления был бы огромным. Затем он проверяет, не сбежал ли сбежавший с карты. Если это так, то это выигрывает! Он отслеживает состояние (каждое предыдущее состояние записывается с каждым состоянием) и строит план (в обратном порядке) перед выходом из цикла BFS. В противном случае он пытается применить каждое действие и добавляет любое, которое можно применить к
due
очередь, перед сортировкой этой очереди, чтобы мы получили состояние наименьшего усилия на следующей итерации.Отформатированный и закомментированный код:
источник