Негідний шлях


21

Негідний шлях

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

Елементи масиву такі:

  1. Порожні пробіли представлені або .або пробілом, і ваш дзвінок;
  2. Вихідна позиція Rogue представлена, звичайно @,;
  3. Золотий шматок представлений символом $;
  4. Стіни представлені #;
  5. Монстри представлені символами з наступного регулярного виразу: [a-zA-Z*&].

Масив не повинен містити жодних символів, які не перераховані вище, тому ви можете припустити, що все, що не є стіною, порожнім простором, шахраєм чи золотом - це чудовисько.

Правила проходження маршруту:

  1. Шахрай може ходити лише через порожні клітини або клітини, що містять золото;
  2. Щоб перейти до сусідньої або діагонально сусідньої комірки, потрібна черга;
  3. Збирання золота відбувається миттєво;
  4. Шахрай не може залишатися поруч або по діагоналі, що примикає до монстра більше ніж один оборот, не прокидаючи його, що заборонено;
  5. Шахрай може входити в зону обізнаності монстра будь-яку кількість разів, монстр прокинеться лише в тому випадку, якщо шахрай витратить два послідовні повороти біля нього.

Правила введення та виводу

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

Це гарантовано, що шахрай не буде біля монстра на початку.

Повна програма або функція добре.

Оцінка балів

Це , оцінка - це кількість байтів для подання, менша кількість кращих.

Тестові кейси

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

1)
@..
.$.
...  -> 1

Просто перевірка на здоровий стан.

2)
@....
...g$
.....  -> 0

Знову перевірка на здоровий стан.

3)
@....
...$g
.....  -> 1

Шахрай може захопити золото, рухаючись ліворуч.

4)
@....g..
.......$
........
.....h..  -> 1

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

5)
@....z..
.......$
.....b..  -> 0

Тактика з попереднього тестового випадку тут не працює - ділянки чутливості монстра перекриваються.

6)
@$#.
###$
....  -> 1

Тест на розум.

7)
@..#..
$.$g.$
...#..  -> 2

Дітто.

8)
@#.d#$
$...##
e.....
..$...
##..$b
.#..g$  -> 3

З усього золота тут можна безпечно дістатись лише до трьох: золото біля вихідного положення можна дістати, перемістившись вниз, а потім назад у вихідне положення. Щоб вирватися з верхнього лівого кута, шахрай повинен двічі рухатися по діагоналі вниз-вправо. Золото в середині не представляє жодних викликів. Зовнішнє золото охороняється gі bможе бути отримано шляхом переміщення по діагоналі від місця праворуч від середнього золота , а потім назад. Решту неможливо отримати: золото вгорі праворуч перекрито стінами, а золото в нижньому правому куті потребує двох оборотів у місцях чутливості монстра.

Наступні тестові випадки були щедро подаровані mbomb007.

9)
  12345678
a @....g.D
b .......$
c ......#.
d .....h..  -> 1

Цей хитрий. Шлях є b4-b5-c6-b7-c8-b8(grab).

10)
  12345678
a @....g.D
b .......$
c .......#
d .....h..  -> 1

Шлях є [bc]4-c5-b6-c7-b8(grab).

11)
  12345678
a @....g.D
b ......#$
c .......#
d .....h..  -> 1

Додаткова стіна насправді нічого не змінює, [bc]4-c5-b6-c7-b8(grab)все одно це рішення.


Вам слід додати більший і складніший приклад. Також які мінімальні та максимальні розміри підземелля? Чи є підземелля 1x1 @дійсним входом?
mbomb007


@ mbomb007 Я додав новий приклад. Щодо розміру сітки, я вважаю, що обмеження її принаймні 3х3 є розумним.
Михайло

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

Почувайся вільно. Саме для цього я і зробив їх. Можна також зазначити, що обертання тестового випадку не повинно впливати на його результат.
mbomb007

Відповіді:


5

попередні рішення (їх частину) можна знайти у контейнері нижнього колонтитулу у посиланні tio (вони, ймовірно, більш читабельні)

JavaScript (Node.js) , 883 436 411 360,345 311 байт

g=>g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A
P=(g,x,y,m={},p={},I=i=9,M={})=>{if(/[.$]/.test(c=(g[y]||0)[x])){for(;i--;)if(/^[^.@$#]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])){if(m[C])return
M[C]=1}for(;I--;)if(!p[(X=x+~-(I/3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return 1}return c=="@"}

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

Пояснення -

замість того, щоб перейти від гравця до готівки, я перейшов із справи до @. Я думаю, що я повинен бути швидшим, тому що я знаю, коли потрібно зупинити пошук (дістатися до @), і коли ти шукаєш готівку, потрібно постійно рухатись, поки ти не покриєш усі плями (і способи дістатися до них). тому альго таким чином досить простий - основна функція g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A: знайдіть готівку -> якщо ви її знайшли -> почніть шукати гравця -> якщо ви знайшли його -> приріст А тепер давайте потрапив до шукача шляху aka P if(/[.$]/.test(c=(g[y]||[])[x]))просто перевірте, чи поточна комірка є "особливою" -> якщо так, ми хочемо повернутися, якщо її гравець. особливі випадки: @ # (монстр)

for(;i--;) if(/^[a-zA-Z*&]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])) -> if my neighbor is a monster {if(m[C])return false -> and it already was in the previous turn - this path is not value M[C]=1} -> if not just add it to the neighbors monsters for(;I--;) if(!p[(X=x+~-(I / 3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return true повторіть повторення сусідів - якщо я ще не був там (p - шлях, який пройшов), продовжуйте шлях (дзвоніть P)


Приємного гольфу! Я помітив декілька речей: (1) ваш код має зайвий пробіл у другому та сьомому рядках, і більшість розривів рядків не потрібні (лише рядки 1 та 6 потребують перерви) та I / 3не потребують місця. Усуньте цей пробіл і ваш рахунок насправді 324! (2) return true може бути return 1(truthy значення) і return falseможе бути просто return(мається на увазі undefined, значення фальси). (3) Регекс ^[^.@$#]$для перевірки на відсутність монстрів коротший, ніж ^[a-zA-Z*&]$перевірка монстрів. Хороша робота!
апспіллери

так, я знаю, що можу зробити це набагато коротше :)
DanielIndie

@apsillers оновлено до простору безкоштовне рішення :)
DanielIndie
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.