Втеча з офісу: плануйте вихід!


32

Це заключний спринт ... і половина вашої команди погана. Ти працюєш із запізненням, просто робиш останній день на день, з нетерпінням чекаєш ... чому вимкнули світло? Я не пам’ятаю охоронця, який приїжджав ... о, ні! Я залишив ключі вдома!

Коли жах обернеться, ви вирішите, що збираєтесь втекти .

Підсумок завдань

Для здійснення втечі вам потрібен план! Однак ви знаєте, що будь-який план має шанс провалитися, а різні плани вимагають різної кількості зусиль.

Будучи голодним, втомленим та інженером, ви вирішили написати коротку програму, щоб визначити найкращий спосіб уникнути комплексу, врівноважуючи проблеми ймовірності успіху та зусиль, які знадобляться.

Ви складаєте карту будівлі:

#######################
#                =    #
!                =    !    <-- window
#          !     =    #        (freedom!)
#################=    #
#    #           =    #
#    #           =    #
#    #           =    #
# o  !   # #  !  =    #
##|  !  ## #  !  =    #
#######################

  ^  ^           ^
  me my door     ludicrously high shelves
     (locked)    (climbable)

Щоб вийти з офісу, вам доведеться відійти від карти. Тут ви бачите, що є два вікна ( !), і кожне з них призведе вас до свободи, але доступне лише одне з них. Ми визначаємо "вимкнути карту" як ноги поза межами карти

Типи клітин

  - 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 стор." означає, що це коштує 1 ст.: ми визначаємо "stp" як кількість енергії, необхідної для кроку.

"дзеркало" означає, що ця дія має дві форми. Показано дію "праворуч", дія "ліворуч" - це точно дзеркало, наприклад:

.o
.|
 # 

є дзеркальною (лівою) формою

o.
|.
# 

Права дія називається "Право" (наприклад, "Крок вправо") Ліва дія називається "Ліворуч" (наприклад, "Крок вліво")

На цих діаграмах втікач показаний

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|

Падіння (підставка)

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), як подібний 1-мірний масив або двовимірний масив. Якщо обраний формат введення певним чином не вказує ширину чи висоту карти, ви можете прийняти додаткові аргументи для цього (ви повинні чітко вказати це у своїй відповіді). Ви можете змішувати аргументи командного рядка та стандартний ввід, якщо він вам підходить (наприклад, карта зі stdin, мінімальна ймовірність успіху від argv). Нижче наведено приклад дійсних та недійсних карт.

Дійсний:

o
|

Дійсний:

  #     #
  !   o #
  !   | #
#########

Недійсний (без втечі):

  #     #
  !     #
  !     #
#########

Недійсний (втеча завжди починає стояти):

  #     #
  !     #
  !   % #
#########

Недійсний (недійсний символ):

  #     #
  !  ~  #
  !     #
#########

Недійсний (не прямокутник / рядки різної довжини):

  #     #
  !   o #
  !   | # 
#########

Ви можете вважати, що ваше введення дійсне (мені байдуже, що робить ваша програма, якщо вона введена недійсною).

Вихід

Вихід - текст (ASCII). Може бути повернуто у вигляді рядка або надруковано до стандартного виводу. План повинен бути розмежований 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щоб переглянути докладніші відомості. Приклади рішень для цих тестових випадків є в іншій суті .

Весь код є повним безладом (хоч і без вогків), але вам не потрібно відхилятися від static void Main(...)зміни обсягу випуску (не соромтесь використовувати цю інформацію, я надав її на вашу користь!).

Проходження тестового випадку не обов'язково означає, що ваш результат добре сформований, оскільки сценарій та перевіряючий пристрій дуже щедрі. Висновок повинен відповідати вищевказаній специфікації, щоб ваше подання було дійсним.

Якщо ви думаєте, що ви знайшли помилку з розв’язувачем чи тестовим сценарієм, помилкою чи тестовою випискою file.txt, то, будь ласка, прокоментуйте цей пост або іншим чином надішліть мені повідомлення в SE Chat; Я, мабуть, не помітив жодної іншої спроби спілкування.

Я не надаю тестовий сценарій у Bash або Batch, тому що я їх не знаю, але я радий включити переклад і напишу версію C #, якщо люди хочуть її.

Пост Амбл

Є питання? Не зволікайте, запитайте їх сьогодні!

Це завдання має на меті вимагати зусиль , дати серйозним гольфістам щось, у що зануриться.

Дякую ais523 за відгуки про вхід / вихід.

Я можу надати більше тестів у файлі суті, якщо люди хочуть більше (не хочу, щоб ця публікація більше не ставала) або хочуть надати деякі свої.


2
Великий виклик! Я обов’язково зроблю це, коли встигну. :)
Р. Кап

Ви знаєте, небезпеку падіння (а точніше швидке уповільнення на дні) можна було б змоделювати, надавши переходу краплі вірогідність 95% або близько того. ;) Приємний виклик!
Мартін Ендер

ви можете врятуватися, хоча небо світла або тунелі? тобто верхній або нижній частині поля? або лише ліворуч чи праворуч?
Moogie

@Moogie ти справді можеш! Поки ваші ноги вільні, ви вільні (наприклад, дивіться випробувальну шафу 1x2, де рішення просто один раз випаде). Я додам невелику тестову скриньку до суті, щоб перевірити сходження зі стелі.
VisualMelon

3
Додано щедрість до питання. Це чудове питання, яке заслуговує на відповіді.
програміст5000

Відповіді:


3

Perl 5, 1425 1464 1481 1469 1485 1438 байт

Це було веселим викликом! І, шокуюче, схоже, у мене найкоротший код поки що трохи менше 1,5 КБ! :)

Досить впевнений, що я нарешті дійшов до цього. Використовуваний роздільник є :, а додаткові прокладки мають два ряди вгорі та один стовпчик з обох боків . Отже, для вашого внеску:

60
#########
# ! #   #
! ! ! o #
! # ! | #
#########

моя програма зайняла б: (Зверніть увагу: на кінці має бути двокрапка, але не на початку!)

60
#########:# ! #   #:! ! ! o #:! # ! | #:#########:

Я використовую регулярні вирази для перекладу з однієї карти на іншу і вирішення грубою силою. Однак я не додаю карти до списку, якщо ця карта вже була досягнута з меншими зусиллями та більшою або однаковою ймовірністю. Карти вилучаються зі списку, коли всі можливі рухи з цієї точки вичерпані. Програма закінчується успішно, коли вона відповідає регексу, який показує, що я досяг бічної або нижньої частини, і закінчується на "Надії немає!" коли список карт вичерпаний.

На жаль, для зняття декількох байт виявилася велика ефективність, тому версія для гольфу є досить повільною;) Здається, що Perl, зокрема, є досить болючою.

Без подальших потреб,

chop($P=<>,$_=<>);s/:/ : /g;$w++until/:.{$w}:/;$z=$"x$w;$_="(.{".$w--."})"for($c,$h,$i,$j);$_="$z:$z: $_$z";$n="[ =]";$d="([!#])";@s=split/,/,'Drop,Drop (Stand),Stepx,Climb offx,Shufflex,Clamber Upx,Put your back into it!x,Punchx,Kickx,Short Jumpx,Long Jumpx,High Jumpx,Crouch,Stand,Climb Up,Stamp';@c=split/,/,"o$c\\|$c$n/ \$1o\$2|,%$c$n/o\$1|,o$n$h\\|$n$h${d}/ o\$1 |\$2\$3,=${c}o$n$h\\|$n$h=/=\$1=o\$2=|\$3=,%$n$h$d/ %\$1\$2,o$n$h\\|${d}$h${d}/ %".'$1 $2$3$4,'."o!$n$i\\|!$n$i${d}/  o\$1  |\$2\$3,o!$h\\|$c$d/o \$1|\$2\$3,\\|!$h$d/| \$1\$2,o$n$n$i\\|$n$n$i${d}/  o\$1  |\$2\$3,o$n$n$n$j\\|$n$n$n$j${d}/   o\$1   |\$2\$3,$n$n${h}o$n$h\\|$c$d/ o".'$1 |$2 $3$4,'."o$c\\|$c${d}/ \$1%\$2\$3,$n$c%$c${d}/o\$1|\$2\$3,=${c}o$c\\|/o\$1|\$2=,\\|$c!/|\$1 ";eval"*$_=sub{\$Q=\"$s[$_]\";s/$c[$_]/}"for(0..15);sub M{$_=join":",map{join'',reverse split//}split/:/};push@M,[$_,0,100,$P];$B{$_}=100;@E=(0,0,1,1,3,10,20,8,8,4,7,12,2,4,2,8);@P=map{100-$_}(0,0,0,0,0,5,20,10,15,5,25,10,0,0,0,10);$z='$N=[$_,$G+0,$t,$t[3]*100,"$t[4]$Q\n"];$N->[4]=~s/x/';do{sub A{@N=@$N;if($N[2]/$N[3]>$B{$N[0]}){push@M,$N;$B{$N[0]}=$N[2]/$N[3]}};die"There is no hope!\n"if(!(@M=grep$G-$_->[1]<21,@M));$e=-1;while(++$e<@M){@t=@{$M[$e]};$m=$_=$t[0];die"Required Effort: $t[1]\n$t[4]"if(/([|%]:|:[|%])/||/[|%][^:]*$/||/^$c:[^:]*[%|]/);for$x(0..15){$_=$m;$t=$t[2]*$P[$x];if($G==$E[$x]+$t[1]and$t>=$t[3]*100){&$x;eval"$z Right/";A;$_=$m;M;&$x;M;eval"$z Left/";A;}}}}

Заради розумності, те саме, що з новими рядками та кількома коментарями:

chop($P=<>,$_=<>); #Take input
s/:/ : /g; #Pad columns on either side so escapee can leave that way
$w++until/:.{$w}:/; #Find width
$z=$"x$w;#Setup a blank line for use in padding later
$_="(.{".$w--."})"for($c,$h,$i,$j); #Set up some generic capturing regexes for reuse
$_="$z:$z: $_$z"; #Pad the top and bottom so the escapee can leave those ways
$n="[ =]"; #Regex for nonsolid block
$d="([!#])"; #Regex for solid block
@s=split/,/,'Drop,Drop (Stand),Stepx,Climb offx,Shufflex,Clamber Upx,Put your back into it!x,Punchx,Kickx,Short Jumpx,Long Jumpx,High Jumpx,Crouch,Stand,Climb Up,Stamp'; #Movement names
@c=split/,/,"o$c\\|$c$n/ \$1o\$2|,%$c$n/o\$1|,o$n$h\\|$n$h${d}/ o\$1 |\$2\$3,=${c}o$n$h\\|$n$h=/=\$1=o\$2=|\$3=,%$n$h$d/ %\$1\$2,o$n$h\\|${d}$h${d}/ %".'$1 $2$3$4,'."o!$n$i\\|!$n$i${d}/  o\$1  |\$2\$3,o!$h\\|$c$d/o \$1|\$2\$3,\\|!$h$d/| \$1\$2,o$n$n$i\\|$n$n$i${d}/  o\$1  |\$2\$3,o$n$n$n$j\\|$n$n$n$j${d}/   o\$1   |\$2\$3,$n$n${h}o$n$h\\|$c$d/ o".'$1 |$2 $3$4,'."o$c\\|$c${d}/ \$1%\$2\$3,$n$c%$c${d}/o\$1|\$2\$3,=${c}o$c\\|/o\$1|\$2=,\\|$c!/|\$1 ";#Movement regexes
eval"*$_=sub{\$Q=\"$s[$_]\";s/$c[$_]/}"for(0..15); #Setup methods to apply regexes. Name of these methods are 0,1,2,3, etc, so we can easily call them in a loop
sub M{$_=join":",map{join'',reverse split//}split/:/}; #Method to mirror the map. All the regexes are right-moving, so the mirror effects are achieved by M;&$x;M
push@M,[$_,0,100,$P]; #Array for initial map position. Encodes: [Map,Effort value,Probability value 1,Probability value 2,Movements(initially undef)]. Two integers are used for the probability to avoid floating point (although after enough steps they overflow and are automatically converted to f.p.)
$B{$_}=100; #Hash map to hold best probability of reaching a map. A new map is never added if it requires at least as much effort and doesn't give a better probability.
@E=(0,0,1,1,3,10,20,8,8,4,7,12,2,4,2,8); #Effort values
@P=map{100-$_}(0,0,0,0,0,5,20,10,15,5,25,10,0,0,0,10); #Probability values
$z='$N=[$_,$G+0,$t,$t[3]*100,"$t[4]$Q\n"];$N->[4]=~s/x/'; #Setup map values
do{ #Loop over all efforts. Do-while loop starts at undef, which is converted to zero automatically when used in a numeric context
    sub A{@N=@$N;if($N[2]/$N[3]>$B{$N[0]}){push@M,$N;$B{$N[0]}=$N[2]/$N[3]}}; #Method to add a map to list.
    die"There is no hope!\n"if(!(@M=grep$G-$_->[1]<21,@M)); #Pares away maps that no longer can produce new maps, and prints "There is no hope!" to stderr if there are no maps left.
    $e=-1;
    while(++$e<@M){ #Loop over all maps. Note that this loops over even maps that are created during the loop
        @t=@{$M[$e]}; #Dereference info about each map
        $m=$_=$t[0]; $Setup map variables
        die"Required Effort: $t[1]\n$t[4]"if(/([|%]:|:[|%])/||/[|%][^:]*$/||/^$c:[^:]*[%|]/); #Checks if escaped, and gives message if so.
        for$x(0..15){
            $_=$m; #Put map into $_
            $t=$t[2]*$P[$x]; #Probability calculation
            if($G==$E[$x]+$t[1]and$t>=$t[3]*100){ #If effort values are right and probability is over threshold
                &$x; #Run regex
                eval"$z Right/"; #Set up map info
                A; #Add map to list @M (only if probability works out right)
                $_=$m;
                M;&$x;M; #Same thing, but mirrored now (generates movement left)
                eval"$z Left/";
                A;
            }
        }
    }
}while(++$G)

Я вже бачу пару місць, щоб випаровувати ще кілька байт, але я не хочу ще раз проходити тестування. Пізніше! :)

Редагувати: Додано трохи підкладки внизу, а також, щоб точніше підходити до ваших результатів під час втечі через підлогу. Деякі з овалів видалено, тож код також може працювати швидше!

Редагувати: Не справлялися з трапами та падіннями цілком правильно. Досі не справляється з драбинами цілком правильно ... Намагаючись це виправити зараз.


Радий, що хтось із цим розважиться! Я боюся, що я не можу прийняти це так, як це є зараз, тому що ви не можете припустити, що вхідні дані мають додаткові рядки або прокладки вгорі (але при ~ 1,5 КБ, просто вставляючи їх не повинно зашкодити забагато!). У мене немає Perl на цій машині, але я спробую знайти спосіб перевірити це сьогодні, тому я можу перевірити, чи працює він і працює у розумний часовий проміжок, і звітувати про це!
VisualMelon

1
@VisualMelon Немає проблем, я змінив метод введення та додав прокладку вручну. Він, як правило, роздувається у більших загадках, але працює у розумні часові рамки для більшості ваших тестових випадків.
Кріс

Все ще не перевірено це, але зауважу, ви сказали, що для цього використовується регулярний вираз для виявлення, коли ви йдете збоку або знизу, але ви також можете втекти з верху (див. Testcase10, який був доданий для цієї мети), про всяк випадок, якщо ви пропустили це
VisualMelon

1
@VisualMelon Ах, я припускав, що для втечі з даху втікачу доведеться піднятися зверху кімнати, а потім піти в бік, з даху. Зараз я бачу відповідне речення. Я це виправлю :)
Кріс

2
Чи можете ви додати посилання TIO?
програміст5000

3

C #, 1814 1481 1395 байт

Яке гасло !! Я зараз дуже задоволений цим!

using C=System.Console;using System.Linq;class S{string M,N="";int x,y,E,c;decimal P=1;static void Main(){int W=0,H=0,x,i,j,k,X,Y,f,m,P=int.Parse(C.ReadLine());string l,M="",B,R="There is no hope!";for(;(l=C.ReadLine())!=null;H++,M+=l)W=l.Length;x=M.IndexOf("|");var D=new[]{new S{M=M,x=x%W,y=x/W}}.ToList();for(var N=D.ToDictionary(s=>R,s=>D);D.Count>0;D.Sort((z,w)=>z.E-w.E)){S s=D[f=0];D.Remove(s);var n=N[l=s.x+s.M+s.y+s.c]=N.ContainsKey(l)?N[l]:new S[0].ToList();if(n.All(o=>o.P<s.P|o.E>s.E)){n.Add(s);X=s.x;Y=s.y;if((X|Y|-X/W-Y/H)<0){R="Required Effort: "+s.E+s.N;break;}for(var A="0110d,Step,*** * #*,0110d,Climb off,=** * =*,3310d,Shuffle,***** #*,2:1/_,Clamber Up,*** *##*,0420_,Short Jump,****  *  #**,0730K,Long Jump,*****   *   #***,0<1/Z,High Jump,  * **#*,0D20P,Put your back into it!,****! *! #**,0800Z,Punch,***!**#*,0800U,Kick,*****!#*,0001d,Drop,*** ,1001d,Drop (Stand),*** ,2200d,Crouch,***#,1400d,Stand,* *#,020/d,Climb Up,=***,0800Z,Stamp,***!".Split(',');f<26;){l=A[k=f*3%48];B=A[++k]+(f>15?" Right":f>9?"":" Left");M=A[++k];m=f++/16*2-1;var Q=s.M.ToArray();var K=s.P*l[4]>=P&s.c==l[k=0]%2;for(j=Y-3;j++<=Y;)for(i=X;i!=X+m*M.Length/4;i+=m)if((K&="==  *!!##*!*=*|*| o*o ".Contains(""+((i|j)>=0&j<H&i<W?Q[x=j*W+i]:' ')+M[k]))&M[k++]==33)Q[x]=' ';if(K)D.Add(new S{M=new string(Q),N=s.N+"\n"+B,x=X+l[2]%48*m,y=Y+l[3]-48,c=l[0]/50,E=s.E+l[1]-48,P=s.P*l[4]/100});}}}C.Write(R);}}

Спробуйте це в Інтернеті

Повна програма, приймає вхід до STDIN, виводиться в STDOUT. По суті, це переписання мого оригінального рішення, використовуючи простий і неефективно реалізований BFS, щоб знайти оптимальний шлях. Це досить швидко, не може бути набагато повільнішим, ніж моя інша реалізація (я не дуже приурочила це, хоча), безумовно, працює в межах часу. Значну частину вартості становить таблиця Дія, яка кодується у вигляді значень, що розділяються комами, які записують назву, карту "match / smash" та інші властивості кожної доступної дії.

Починається з читання з мінімальною вірогідністю успіху та карти. Потім він знаходить втікача, видаляє його з карти та створює "стан пошуку", що містить цю інформацію. Потім він виконує BFS, який неодноразово дивиться на наступний належний стан з найменшими зусиллями (гарантуючи, що він знайде оптимальне рішення). Перш ніж розширювати вузол, він порівнює зусилля та ймовірність успіху з попередніми вузлами з тією ж картою та місцем розташування евангелістів та відхиляє себе, якщо вже знайдено кращий маршрут до цього стану. Якщо він пережив це, він додає себе до таблиці "бачення", щоб згодом відхилити стан. Це все для продуктивності, і без цього фактор розгалуження був би величезним. Потім він перевіряє, чи не втікач не з карти. Якщо є, то перемагає! Він відстежує стан (кожен попередній стан записується з кожним станом) і будує план (у зворотному порядку) перед виходом із циклу BFS. В іншому випадку він намагається застосувати кожну дію та додає будь-яку, яку можна застосувати доdue перед сортуванням цієї черги, щоб ми отримали найменше зусилля наступної ітерації.

Форматований та коментований код:

using C=System.Console;
using System.Linq;

// ascii
//   32
// ! 33
// = 61
// . 46
// * 42
// # 35
// | 124
// 0 48

class S // SearchState
{
    string M, // map
        N=""; // plan
    int x, // pos x
        y, // pos y
        E, // effort
        c; // crouching?
    decimal P=1; // chance (Probability)

    static void Main()
    {
        int W=0, // map width
            H=0, // map height
            x, // various temps
            i, // local x
            j, // local y
            k, // position in match/smash map
            X, // s.x
            Y, // s.y

            // action loop
            f, // T idx
            m, // A idx, action mirror (direction)

            P=int.Parse(C.ReadLine()); // probability of success constraint

        string l, // line, Act 'block' params, map hash, match pairs; all sorts!
            M="", // initial map
            B, // name of action
            R="There is no hope!"; // result string

        // read map
        for(;(l=C.ReadLine())!=null; // while there is input to read
            H++,M+=l) // increment height, and append to M
            W=l.Length; // record width

        // detect the escapee
        x=M.IndexOf("|");

        // create first state, and add it to Due list
        var D=new[]{new S{M=M,x=x%W,y=x/W}}.ToList();

        // 'seen' table, stores all the states we've been in which looked similar
        for(var N=D.ToDictionary(s=>R,s=>D); // these values are meaningless (and necessarily can't interfere), we just use it to save having to spec the type
            D.Count>0; // keep going until we run out of states to expand (-> no escape)
            D.Sort((z,w)=>z.E-w.E)) // enforce Breadth First Search
        {
            // get next State to expand, and remove it from Due
            S s=D[f=0];
            D.Remove(s);

            // retrieve or create seen list
            var n=N[l=s.x+s.M+s.y+s.c]= // store it, and cache it, l is 'hash', containing map and escapee state
                N.ContainsKey(l)? // already got a seen list for ths map?
                N[l]: // then use it!
                new S[0].ToList(); // otherwise create a new (empty) one

            // perf: only proceed if we havn't seen this map with better Effort and Chance yet
            if(n.All(o=>o.P<s.P|o.E>s.E))
            {
                // record that we have been seen
                n.Add(s);
                X=s.x;
                Y=s.y;

                if((X|Y|-X/W-Y/H)<0) // check if we our outside the bounds - this took 2.5hour to write. 1 byte.
                { // quit if both are positive or both are negative
                    // freedom
                    R="Required Effort: "+s.E+s.N;

                    // finished
                    break;
                }

                // [Crouch,Effort,dx,dy,Probability],Name,MatchSmash (first 10 are mirrors)
                // 0110d,Step,*** * #*,
                // 0110d,Climb off,=** * =*,
                // 3310d,Shuffle,***** #*,
                // 2:1/_,Clamber Up,*** *##*,
                // 0420_,Short Jump,****  *  #**,
                // 0730K,Long Jump,*****   *   #***,
                // 0<1/Z,High Jump,  * **#*,
                // 0D20P,Put your back into it!,****! *! #**,
                // 0800Z,Punch,***!**#*,
                // 0800U,Kick,*****!#*,
                // 0001d,Drop,*** ,
                // 1001d,Drop (Stand),*** ,
                // 2200d,Crouch,***#,
                // 1400d,Stand,* *#,
                // 020/d,Climb Up,=***,
                // 0800Z,Stamp,***!

                // attempt to expand this node with every action
                for(var A="0110d,Step,*** * #*,0110d,Climb off,=** * =*,3310d,Shuffle,***** #*,2:1/_,Clamber Up,*** *##*,0420_,Short Jump,****  *  #**,0730K,Long Jump,*****   *   #***,0<1/Z,High Jump,  * **#*,0D20P,Put your back into it!,****! *! #**,0800Z,Punch,***!**#*,0800U,Kick,*****!#*,0001d,Drop,*** ,1001d,Drop (Stand),*** ,2200d,Crouch,***#,1400d,Stand,* *#,020/d,Climb Up,=***,0800Z,Stamp,***!".Split(','); // Act string
                    f<26;) // read A into T // (cycle over first 10 twice, making them mirrors)  (very convieniently, 3*16==48=='0'==x!)
                {
                    // 'parse' next action
                    l=A[k=f*3%48]; // [Effort,Crouch,dx,dy,Probability]
                    B=A[++k]+(f>15?" Right":f>9?"":" Left"); // action name
                    M=A[++k]; // Match and Smash table (4x?, escapee at 0,2, #: solid, !: smashable (and is smashed), .: empty,  : don't care, =: climable)
                    //c=l[1]-48; // crouching transition (0: standing -> standing, 1: crouching -> standing, 2: standing -> crouching, 3: crouching -> crouching)
                    m=f++/16*2-1;

                    // this will be the new map
                    var Q=s.M.ToArray();

                    // K is whether we are allowed to apply this action
                    var K=s.P*l[4]>=P& // within chance limit
                        s.c==l[k=0]%2; // crouching matches

                    // compare the map to the Match/Smash map, to make sure we can apply this transform (and smash any ! we meet)
                    for(j=Y-3;j++<=Y;) // for the 4 rows
                        for(i=X;i!=X+m*M.Length/4;i+=m) // for each column (a.M has height 4, but variable width)
                            if((K&= // K still true?
                                "==  *!!##*!*=*|*| o*o ".Contains(""+ // check for an allowed pairing (cache pairing in M) (this includes the escapee, much cheaper to do this than remove him)
                                    ((i|j)>=0&j<H&i<W?Q[x=j*W+i]:' ') // we are within bounds and match, we are out of bounds (empty)
                                    +M[k])) // char from MatchSmash map
                                &M[k++]==33) // if it is destructible ('!' == 33)
                                Q[x]=' '; // then blank it out (x is necessarily set by the cell check)

                    if(K) // if K holds
                        D.Add(new S{M=new string(Q),N=s.N+"\n"+B, // assemble plan as we go (this will chew up memory, but none of the problems are big enough for it to matter)
                            x=X+l[2]%48*m,y=Y+l[3]-48,c=l[0]/50,E=s.E+l[1]-48,P=s.P*l[4]/100}); // add the resulting state to Due
                }
            }
        }

        C.Write(R);
    }
}

Хороша робота! Мене нескінченно дивує, що ваш старий бал та новий бал - це анаграми один одного ... lol
HyperNeutrino

Чи побив С # Perl?
Esolanging Fruit
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.