Життя - це лабіринт: ми пішли неправильним Шляхом, перш ніж навчилися ходити


30

Вхід:

Лабіринт, що містить символів:

  • -- (горизонтальна стіна);
  • | (вертикальна стіна);
  • + (з'єднання);
  • (прогулянковий простір);
  • I (вихід);
  • U (Вхід).

Тобто вхід може виглядати так:

 +--+--+--+--+--+--+--+--+--+--+ 
I               |     |        | 
 +  +--+--+--+  +  +  +  +--+  + 
 |           |     |  |  |     | 
 +--+--+--+  +--+--+  +  +  +--+ 
 |           |     |     |     | 
 +  +--+--+  +  +--+--+  +--+  + 
 |     |     |     |     |     | 
 +--+  +  +--+--+  +--+--+  +  + 
 |     |        |        |  |  | 
 +  +--+--+--+  +--+--+  +  +  + 
 |     |     |     |        |  | 
 +--+  +  +--+--+  +--+--+--+--+ 
 |  |  |                 |     | 
 +  +  +--+--+--+  +--+  +  +  + 
 |     |        |  |  |  |  |  | 
 +--+--+  +  +--+  +  +  +--+  + 
 |        |     |     |  |     | 
 +  +--+--+--+  +  +  +  +  +--+ 
 |           |     |  |         U
 +--+--+--+--+--+--+--+--+--+--+ 

Вихід:

Найбільш ефективний шлях , який ви повинні пройти , щоб отримати від входу до виходу з лабіринту (через лабіринт), позначений позначають вліво, вправо, вгору і вниз (тобто >; <; ^; v).

Правила виклику:

  • Ви можете взяти дані в будь-якому розумному форматі. String-масив, одиночний рядок з новими рядками, 2D char-масив тощо - це всі можливі вхідні формати.
  • Вихід може складатися з будь-яких чотирьох різних символів. Тобто ><^v; →←↑↓; ⇒⇐⇑⇓; RLUD; 0123; ABCD; тощо).
  • Ви можете додати пробіли або проміжку нового рядка до виводу, якщо бажано; це необов’язково.
  • Етапи рахуються на квадрат (див. Чотири +символи для квадратів), а не на один символ.
  • Лабіринт може бути розміром від 5x5 до 15x15, і завжди буде площею (тому тестів для 5x10 лабіринтів не буде).
  • Ви можете припустити, що кожен лабіринт має один або більше дійсних шляхів від початку до кінця, і ви завжди отримуєте найкоротший (див. Тестові випадки 4 та 5).
  • Якщо є кілька шляхів з однаковою довжиною, ви можете вибрати, який з них вивести (див. Тестовий випадок 6).
  • Ви не можете «ходити» за межі лабіринту (див. Тестові випадки 7 та 8).

Загальні правила:

  • Це , тому найкоротша відповідь у байтах виграє.
    Не дозволяйте мовам коду-гольфу відштовхувати вас від публікації відповідей з мов, що не кодують гольф. Спробуйте придумати якомога коротшу відповідь на "будь-яку" мову програмування.
  • Для вашої відповіді застосовуються стандартні правила , тому вам дозволяється використовувати STDIN / STDOUT, функції / метод з відповідними параметрами, повноцінні програми. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду.
  • Також, будь ласка, додайте пояснення, якщо це необхідно.

Тестові приклади:

1. Input:
 +--+--+--+--+--+--+--+--+--+--+ 
I               |     |        | 
 +  +--+--+--+  +  +  +  +--+  + 
 |           |     |  |  |     | 
 +--+--+--+  +--+--+  +  +  +--+ 
 |           |     |     |     | 
 +  +--+--+  +  +--+--+  +--+  + 
 |     |     |     |     |     | 
 +--+  +  +--+--+  +--+--+  +  + 
 |     |        |        |  |  | 
 +  +--+--+--+  +--+--+  +  +  + 
 |     |     |     |        |  | 
 +--+  +  +--+--+  +--+--+--+--+ 
 |  |  |                 |     | 
 +  +  +--+--+--+  +--+  +  +  + 
 |     |        |  |  |  |  |  | 
 +--+--+  +  +--+  +  +  +--+  + 
 |        |     |     |  |     | 
 +  +--+--+--+  +  +  +  +  +--+ 
 |           |     |  |         U
 +--+--+--+--+--+--+--+--+--+--+ 

1. Output:
>v>>>vv<v>>v>v>>vvv>>>

2. Input:
 +--+--+--+--+--+ 
I   |        |  | 
 +  +--+--+  +  + 
 |        |  |  | 
 +  +--+  +  +  + 
 |  |  |     |  | 
 +  +  +--+  +  + 
 |        |     | 
 +--+  +  +--+--+ 
 |     |         U
 +--+--+--+--+--+ 

2. Output:
>vvv>>v>>>

3. Input:
 +--+--+--+--+--+ 
U      |        | 
 +  +  +--+--+  + 
 |  |     |     | 
 +--+--+  +  +--+ 
 |        |     | 
 +  +--+--+--+  + 
 |  |     |     | 
 +  +  +  +  +--+ 
 |     |         I
 +--+--+--+--+--+ 

3. Output:
<<<^<v<^^>>^<^<<

4. Input (test case with two valid paths):
 +--+--+--+--+--+ 
U      |        | 
 +  +  +--+--+  + 
 |  |           | 
 +--+--+  +  +--+ 
 |        |     | 
 +  +--+--+--+  + 
 |  |     |     | 
 +  +  +  +  +--+ 
 |     |         I
 +--+--+--+--+--+ 

4. Output:
<<^>^<^<<^<<     (<<<^<v<^^>>^<^<< is less efficient, and therefore not a valid output)

5. Input (test case with two valid paths):
                               I
+--+--+--+--+--+--+--+--+--+--+  +--+--+--+--+
|     |              |                    |  |
+  +  +  +--+--+--+  +  +--+--+  +--+--+  +  +
|  |     |        |     |        |     |     |
+--+--+--+  +--+  +  +--+--+--+--+  +--+--+--+
|     |  |  |  |     |     |           |     |
+  +  +  +  +  +--+  +  +  +  +--+--+  +--+  +
|  |        |        |  |     |        |     |
+  +--+--+--+  +--+--+  +  +--+  +--+--+  +--+
|  |     |     |        |  |     |     |     |
+  +--+  +  +--+  +--+--+  +--+--+  +  +--+  +
|  |     |        |     |           |        |
+  +  +--+--+--+--+  +  +--+--+--+  +--+  +--+
|     |     |        |        |  |     |     |
+--+--+--+  +  +--+--+  +--+  +  +--+  +--+  +
|              |     |     |        |  |  |  |
+  +--+--+--+--+  +  +  +--+--+--+  +  +  +  +
|     |  |     |  |  |        |        |  |  |
+--+  +  +  +  +  +  +--+--+  +  +  +--+  +  +
|     |     |  |  |  |           |  |     |  |
+--+  +--+--+  +  +  +  +--+--+--+  +  +  +  +
|     |        |  |  |     |        |  |  |  |
+  +--+  +--+--+  +  +--+--+  +  +--+  +  +  +
|        |     |  |     |     |  |     |  |  |
+--+--+--+  +  +  +--+  +  +--+--+  +--+  +  +
|  |        |        |     |        |     |  |
+  +  +--+--+--+--+  +--+--+  +--+--+  +--+  +
|  |              |              |     |     |
+  +  +  +--+--+--+--+--+--+--+--+  +--+  +--+
|     |                                |     |
+--+--+--+--+--+--+--+--+--+  +--+--+--+--+--+
                            U

5. Output:
v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv<^<v<<v>v>>>>>>>v     (v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv>v>>>^>>^>^^>vvv<v<v<<v is less efficient, and therefore not a valid output)

6. Input:
 +--+--+--+--+--+
I               |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |               U
 +--+--+--+--+--+

6. Output:
>>v>v>v>v> or >v>v>v>v>> or >>>>>vvvv> or etc. (all are equally efficient, so all 10-length outputs are valid)

7. Input:
 I  U
+  +  +--+--+--+
|  |        |  |
+  +--+--+  +  +
|     |     |  |
+--+  +  +--+  +
|        |  |  |
+  +--+  +  +  +
|     |        |
+--+  +--+--+  +
|     |        |
+--+--+--+--+--+

7. Output:
vv>v>^>^<<^

8. Input:
 +--+--+--+--+--+
 |     |        |
 +  +--+  +--+  +
I   |     |  |  |
 +  +  +--+  +  +
U   |     |  |  |
 +--+--+  +  +  +
 |     |     |  |
 +  +--+--+--+  +
 |               
 +--+--+--+--+--+

8. Output:
>v<

Лабіринти, що генеруються за допомогою цього інструменту (а в деяких випадках трохи змінених).


10
Я знайшов коротше рішення для третього тестового випадку! v<<<<<<^^^^^(завжди думайте поза скринькою)
Лев

2
Якщо можна довести, що їх код дасть найкоротше рішення з урахуванням достатнього часу та пам'яті, чи змагається він? Навіть у випадку дійсно тривалого часу (кінець світобудови)?
Yytsi

1
@JackBates Це жарт. Він буквально обходить коробку до виходу: D
Yytsi

1
Я думаю, що перший тестовий випадок неправильний, він повинен бути >v>>>vv<v>>v>v>>vvv>>>.
smls

1
@KevinCruijssen Наприклад, рішення, яке тестує кожну комбінацію "v ^ <>" на довжину до кількості порожніх коробок всередині лабіринту. Правильне рішення знайдеться, але для обчислення потрібен астрономічний час.
Yytsi

Відповіді:


7

Сітківка , 338 281 275 273 261 байт

¶U
¶&
+`·(\w.+)$
|$1
((.)+I.+¶.+¶(?<-2>.)+)·
$1v
+`((.)*)\+(.).*(¶(?<-2>.)*.)((\w)|·)·?
$1$4$.4$3$6
·v
-v
G`1
·U
&
{`\B·\d+.(\w+)
$1K$&
(\w+)·\d+.\B
$&$1r
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v
)`\D(\d+).\B(?=.+¶.*\D\1·(\w+))
$&$2A
^.+\d·(\w+)
&$1A
M!`&\w+
I|&

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


Примітки

  • Через значні пробіли всі пробіли ( 0x20) замінюються інтерпунктом ( ·) як у цій відповіді, так і посиланням TIO. Програма працює чудово, якщо пробіли відновлені.
  • Використання AvKrвідповідно вгору, вниз, вліво та вправо. Вони можуть бути замінені будь-якими літерами, крім I.
  • Займає близько 40-х років на TIO для тестового випадку 15 × 15. Будьте терплячі. Переробили частину для пошуку найкоротшого шляху, як тільки шлях дійшов до виходу. Виявляється, це забирало багато часу.
  • Може повністю зламатися на лабіринтах, шириною яких 66 або більше, але може обробляти лабіринти довільної висоти. Виправлення довільної ширини займає +1 байт.

Пояснення

Програма складається з 3 етапів:

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

Формат

Оскільки оригінальний формат лабіринту є досить непростим, перша частина програми перетворює його в інший формат.

Клітини

У вихідному форматі кожна комірка представлена ​​у вигляді області 2 × 3:

+               <top wall>      <top wall>
<left wall>     <data/space>    <space>

Оскільки правий стовпець не містить інформації, програма ідентифікує клітинки як будь-яку область 2 × 2 з а +вгорі зліва.

У нас залишаються 3 види клітин:

  • Я Клітини : Клітини, які належать всередині лабіринту.
  • R клітини : клітини, що знаходяться праворуч від лабіринту. Вони створюються за допомогою прокладки, яка використовується для розміщення входу або виходу. Наприклад, вихід Uу тестовому випадку 1 знаходиться в R-соті.
  • B Клітини : Клітини, що знаходяться нижче лабіринту. Як і R-Cells, вони створюються за допомогою прокладки.

У новому форматі комірки представлені у вигляді рядка змінної довжини:

<left wall> <column number> <top wall/exit marker> <path>

Ліва і верхня стінка скопійовані з оригінального формату. Номер стовпця заснований на горизонтальному положенні комірки і використовується для вирівнювання (ідентифікація комірок безпосередньо зверху / під іншою). Шлях - це алфавітний рядок, який використовується під час фази заповнення для збереження найкоротшого шляху до досягнення цієї комірки. Маркер шляху та виходу буде пояснено далі.

Півклітини

Хоча більшість лабіринтів є клітинами, є ділянки лабіринту, які не є клітинами:

  • R Напівклітинки : Якщо немає правої підкладки, +s уздовж правої стінки не утворює комірок, оскільки вони знаходяться на останньому стовпчику.
  • L Напівклітинки : Якщо є ліва підкладка, клітини не можуть утворюватися там, оскільки їх немає +зліва від них. Наприклад, вхід Iу тестовому випадку 1 знаходиться в пів-клітинці L.

Технічно є T-напівклітинки над лабіринтом (коли є верхня підкладка) та B напівклітини (вздовж нижньої стінки, коли немає нижньої підкладки), але вони не представлені у новому форматі.

Верхній рядок півклітини буде видалено як частина побудови повних комірок у тому ж рядку, тож півклітини представлені у новому форматі як

<wall/exit marker>? <path>

Пів-клітини R просто |. Половина комірок L має Iтакий самий шлях, як маркер виходу та порожній шлях, або просто порожня стінка.

Входи та виходи

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

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

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

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

Нарешті, будь-яка В-комірка, що містить вхід чи вихід, повинна закрити ліву стінку, щоб запобігти "вирішенню" лабіринту, йдучи по В-клітинах. Входи та виходи в R-клітинках або L-півклітинках не потребують подальшої обробки, оскільки алгоритм заповнення затоплення не дозволяє вертикальним рухам до / з них.

Приклад

Як приклад - перший тестовий випадок

·+--+--+--+--+--+--+--+--+--+--+·
I···············|·····|········|·
·+··+--+--+--+··+··+··+··+--+··+·
·|···········|·····|··|··|·····|·
·+--+--+--+··+--+--+··+··+··+--+·
·|···········|·····|·····|·····|·
·+··+--+--+··+··+--+--+··+--+··+·
·|·····|·····|·····|·····|·····|·
·+--+··+··+--+--+··+--+--+··+··+·
·|·····|········|········|··|··|·
·+··+--+--+--+··+--+--+··+··+··+·
·|·····|·····|·····|········|··|·
·+--+··+··+--+--+··+--+--+--+--+·
·|··|··|·················|·····|·
·+··+··+--+--+--+··+--+··+··+··+·
·|·····|········|··|··|··|··|··|·
·+--+--+··+··+--+··+··+··+--+··+·
·|········|·····|·····|··|·····|·
·+··+--+--+--+··+··+··+··+··+--+·
·|···········|·····|··|·········U
·+--+--+--+--+--+--+--+--+--+--+·

є

I·3-·6-·9-·12-·15-|18-·21-|24-·27-·30-|33·
·|3··6-·9-·12-|15··18·|21·|24·|27-·30·|33·
·|3-·6-·9-·12·|15-·18-|21··24·|27··30-|33·
·|3··6-|9-·12·|15··18-|21-·24·|27-·30·|33·
·|3-·6·|9··12-·15-|18··21-·24-|27·|30·|33·
·|3··6-|9-·12-|15··18-|21-·24··27·|30·|33·
·|3-|6·|9··12-·15-·18··21-·24-|27-·30-|33·
·|3··6·|9-·12-·15-|18·|21-|24·|27·|30·|33·
·|3-·6-·9·|12··15-|18··21·|24·|27-·30·|33·
·|3··6-·9-·12-|15··18·|21·|24··27··30-·33&

у новому форматі. Ви можете конвертувати тут інші лабіринти .


Етап будівництва

Етап побудови складає перші 13 рядків програми.

¶U
¶&

Перетворює вихід у L-півклітинки у маркер виходу

+`·(\w.+)$
|$1

Додає стіни зліва від входу та виходу в B Cells

((.)+I.+¶.+¶(?<-2>.)+)·
$1v

Зроби перший крок, якщо вхід знаходиться над лабіринтом

+`((.)*)\+(.).*(¶(?<-2>.)*.)((\w)|·)·?
$1$4$.4$3$6

Виконує фактичне перетворення

·v
-v

Закриває верхній-вхідний отвір

G`1

Тримає лише рядки з a 1. Оскільки лабіринти мають щонайменше 5 комірок, а кількість стовпців відбувається з кроком 3, рядок із комірками нового формату повинен містити номер стовпця між 10 та 19.

·U
&

Перетворює вихід у R Cell або B Cell у маркер виходу


Фаза заповнення

Фаза заповнення складає наступні 8 рядків програми. Він використовує алгоритм заповнення заливів, щоб заповнити всі комірки найкоротшим шляхом, щоб дістатися туди від входу.

{`

Поставляє всю фазу заливки на петлю, щоб заповнити весь лабіринт.

\B·\d+.(\w+)
$1K$&

Кожна клітина, здатна рухатися ліворуч, робить це. Осередок може рухатися ліворуч, якщо

  1. він має не порожній шлях
  2. у нього порожня ліва стінка; і
  3. клітинка або L півклітина зліва має порожній шлях
(\w+)·\d+.\B
$&$1r

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

  1. він має не порожній шлях
  2. клітина праворуч має порожню ліву стінку; і
  3. клітина праворуч має порожній шлях
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v

Потім кожна клітина, здатна рухатися вниз, робить це. Осередок може рухатися вниз, якщо

  1. він має не порожній шлях
  2. він має принаймні одну клітинку або півклітинку праворуч (тобто це не клітина R)
  3. комірка під нею (тобто комірка в наступному рядку з тим же номером стовпця) має порожню верхню стінку або має маркер виходу; і
  4. клітинка під ним має порожній шлях

Зауважте, що напівклітини L не можуть переміщатися вниз, оскільки вони не мають номерів стовпців.

\D(\d+).\B(?=.+¶.*\D\1·(\w+))
$&$2A

Потім кожна клітина, здатна рухатися вгору, робить це. Осередок може рухатися вгору, якщо

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

Фаза повернення

Фаза повернення складає останні 5 рядків програми. Ця фаза шукає і повертає шлях, заповнений у вихідну комірку.

Шаблон шляху на виході залежить від місця виходу:

  1. Якщо вихід знаходиться в пів-клітинці L, то ця півклітина буде & <path>
  2. Якщо вихід у R-клітинку або В-клітинку, то ця клітина буде <left wall> <column number> & <path>
  3. Якщо вихід знаходиться в T Половинці клітини, то, як зазначено вище, I комірка, що веде до виходу, буде <left wall> <column number> · <path>і у верхньому рядку.
^.+\d·(\w+)
&$1A

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

M!`&\w+

Відповідає та повертає не порожній шлях за маркером виходу.

I|&

Видаляє маркер виходу та Iпрефікс шляху.


Чому AvKr? Чи мають вони значення / це скорочення вгору, вниз, вліво та вправо у вашій рідній мові, чи є інша причина, чому ви вибрали саме ці конкретні символи?
Kevin Cruijssen

@KevinCruijssen Просто тому, що я повинен використовувати буквено-цифрові символи і AvKrє найбільш близьким до стрілок у букві.
TwiNight

12

Perl 6 , 259 295 байт

{my \a=S:g/(.)$0+/{$0 x($/.comb+.5)*2/3}/;sub f (\c,\v,*@p) {with (c ne any v)&&a.lines».comb[+c[0];+c[1]] ->$_ {for (/\s/??10011221!!/I/??a~~/^\N*I|I\N*$/??2101!!1012!!'').comb X-1 {f [c Z+$^a,$^b],(|v,c),@p,chr 8592+$++}
take @p if /U/}}
[~] (gather f a~~/(\N+\n)*(.)*I/,[]).min(+*)[1,3...*]}

Як це працює

  1. my \a = S:g/ (.) $0+ /{ $0 x ($/.chars + .5) * 2/3 }/;

Це стискає лабіринт, щоб внутрішня частина кожної комірки була 1х1 замість 2х1 символів пробілу:

 + - + - + - + - + - + + - + - + - + - + - + 
Я | | | Я | | |
 + + - + - + + + + + - + - + + + 
 | | | | | | | |
 + + - + + + + + + - + + + + 
 | | | | | -> | | | | |
 + + + - + + + + + + - + + + 
 | | | | | |
 + - + + + - + - + + - + + + - + - + 
 | | U | | U
 + - + - + - + - + - + + - + - + - + - + - +

  1. sub f (\c,\v,*@p) {
        with (c ne any v) &&                   # If the coordinate wasn't visited yet
             lines».comb[+c[0];+c[1]] -> $_ {  # and a character exists there...
            for (                          # For each vector...
                 /\s/ ?? 10011221 !!       #  from a cell: (0,-1), (-1,0), (0,1), (1,0)
                 /I/  ?? a~~/^\N*I|I\N*$/
                          ?? 2101          #  from a top/bottom entrance: (1,0), (-1,0)
                          !! 1012          #  from a left/right entrance: (0,-1), (0,1)
                      !! ''                #  otherwise: none
                ).comb X-1 {
                f                       #   Recurse with arguments:
                    [c Z+ $^a, $^b],    #     c plus the vector
                    (|v, c),            #     v with c appended
                    @p, chr 8592 + $++  #     p with the correct Unicode arrow appended
            }
            take @p if /U/
        }
    }

Це функція рекурсивного пошуку шляху. Це потребує трьох параметрів: Поточна координата c=(y,x), список вже відвіданих координат vта шлях p, який пройшов досі (як список символів стрілок).

Якщо символ у поточній координаті є пробілом, він повторюється до чотирьох сусідів.
Якщо персонаж на поточній координаті є a I, він повторюється до двох сусідів, які не знаходяться "по краю", щоб змусити рішення пройти лабіринт, а не навколо нього.
Якщо символом у поточній координаті є а U, він викликає takeнакопичений рядок шляху.

  1. [~] (gather f a ~~ /(\N+\n)*(.)*I/, []).min(+*)[1,3...*]

Рекурсивна функція спочатку викликається координатою літери I, яка виявляється за допомогою регулярного вираження.

gatherКлючове слово збирає всі цінності , на яких takeбули званими всередині функції, тобто весь допустимий нециклічних шлях через лабіринт.

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


Перш за все чудова робота над тим, щоб першим виконати своє завдання! :) Розумно, як ви змінили два пробіли на один, щоб полегшити фактичний рух / підрахунок. +1 від мене. У будь-якому випадку, після деяких коментарів, було додано два нових тестові справи. Чи можете ви підтвердити цю роботу і своїм рішенням? (Також у Perl 6 є TIO або інший онлайн-компілятор, на який ви можете додати посилання?)
Кевін Кройсейсен

@KevinCruijssen: У нових тестах він обійшов лабіринт. :( Я виправив код зараз. Tio.run підтримує Perl 6, але чомусь це не працює ... можливо, у нього занадто стара версія Perl 6?
smls

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

Оскільки ти був першим, хто відповів на мій виклик чотири місяці тому, я дав тобі нагороду. :) І Прийміть для трохи коротшої відповіді Ретіна.
Kevin Cruijssen

5

Пітон 2: 302 байти

from re import*
r=lambda x:[''.join(_)for _ in zip(*x)][::-1]
z=',l)for l in s]'
def f(s,b=1,o=0,n=0):
 exec("s=[sub('(..).(?!$)',r'\\1'%s;"%z+"s=r([sub(' I ','+I+'%s);"%z*4)*b+"t=[sub('I  ','@@I'"+z
 if'I U'in`s`or n>3:return`o%4`+n/4*`s`
 return min(`o%4`+f(t,0,o,4*(t==s)),f(r(s),0,o+1,n+1),key=len)

Приймає введення як масив рядків, що мають однакову довжину. Друкує 0праворуч, 1вниз, 2ліворуч та 3вгору.

Пояснення

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

from re import*
r=lambda x:[''.join(_)for _ in zip(*x)][::-1] #Rotates the board counterclockwise
z=',l)for l in s]'    #Suffix for hacky exec golfing
def f(s,b=1,o=0,n=0): #b is 1 on initial call, 0 on every recursion
                      #o is orientation
                      #n is number of rotations
 exec("s=[sub('(..).(?!$)',r'\\1'%s;"%z  #Squeeze the maze
      +"s=r([sub(' I ','+I+'%s);"%z*4)   #Add walls around the I to keep it in the maze
      *b                                 #Only if b is 1
      +"t=[sub('I  ','@@I'"+z            #Attempt to move right

 if'I U'in`s`or n>3:return`o%4`+n/4*`s`  #If the I is next to the U, return the orientation
                                         #If there were 4 rotations, return a long string
 return min(                             #Return the path with the shortest length:
            `o%4`+f(t,0,o,4*(t==s)),       #Moving forward if possible
            f(r(s),0,o+1,n+1),             #Rotating the board
        key=len)

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


3
Ласкаво просимо до PPCG! Це чудова перша відповідь, і я вражений, що ви вирішили зробити досить важкий виклик, як ваш перший. Крім того, розумно, як ви поставили стіни навколо, Iщоб запобігти виходу шляху за лабіринт. Насолоджуйтесь своїм перебуванням та +1 від мене. :)
Кевін Круїссен

2

JavaScript (ES6), 356 байт

a=>(a=a.map(s=>s.filter((_,i)=>!i|i%3)),g=([x,y])=>a[y]&&a[y][x],o=[],c=([x,y],m="",v=[])=>[[0,1],[1,0],[0,-1],[-1,0]].map(([j,k],i)=>(p=[x+j,y+k],!m&(!y|y>a[l="length"]-2)==i%2|v.includes(""+p)||(g(p)<"!"?c(p,m+"v>^<"[i],[...v,""+p]):g(p)=="U"?o.push(m.replace(/(.)\1/g,"$1")):0))),a.map((h,i)=>h.map((k,j)=>k=="I"&&c([j,i]))),o.sort((a,b)=>a[l]-b[l])[0])

Приймає введення як двовимірний масив символів. Кожен рядок повинен бути залитий на один пробіл і не мати пробілу, незалежно від місця початку та кінця.

Використання ідею smls про скріплення лабіринту, щоб зробити кожну клітинку 1x1 та видалити повторні стрілки з виводу.

Необов’язаний і пояснений

a=>(
    a=a.map(s=>s.filter((_,i)=>!i|i%3)),    // squish the maze to 1x1 cells
    g=([x,y])=>a[y]&&a[y][x],               // helper func to get maze value
    o=[],                                   // resulting movesets
    c=([x,y], m="", v=[]) =>                // recursive func to search
                                            // takes current point, moves, and visited spots
        [[0,1],[1,0],[0,-1],[-1,0]].map(([j,k],i)=>(// for each direction
            p=[x+j,y+k],
            !m & (!y | y>a[l="length"]-2) == i%2 |  // if first move, prevent moving out of maze
                v.includes(""+p) || (               // also prevent if already visited
                    g(p)<"!" ?                      // is this a space?
                        c(p, m+"v>^<"[i], [...v,""+p]) // check this spot recursively
                    : g(p)=="U" ?                   // if this the end?
                        o.push(                     // add moves to moveset
                            m.replace(/(.)\1/g,"$1")) // with double arrows removed
                    : 0
                )
        )),

    a.map((h,i)=>h.map((k,j)=>      // find the starting "I" and
        k=="I" && c([j,i])          // begin recursion at that point
    )),

    o.sort((a,b)=>a[l]-b[l])[0]     // get shortest path
)

Тест-фрагмент


1

Сітківка , 416 байт

T` `+`^.*| ?¶.|.*$
I
#
{+` (\w)
d$1
+`(\w) 
$1a
+`(¶(.)*) (.*¶(?<-2>.)*(?(2)(?!))\w)
$1s$3
}+m`(^(.)*\w.*¶(?<-2>.)*(?(2)(?!))) 
$1w
^
w¶
w((.|¶)*(¶(.)*#.*¶(?<-4>.)*(?(4)(?!))(s)|#(d)|(a)#))
$4$5$6¶$1
{`^(.*d)(¶(.|¶)*)#(\w)
$1$4$2 #
^(.*a)(¶(.|¶)*)(\w)#
$1$4$2# 
^(.*s)(¶(.|¶)*¶(.)*)#(.*¶(?<-4>.)*(?(4)(?!)))(\w)
$1$6$2 $5#
}`^(.*w)(¶(.|¶)*¶(.)*)(\w)(.*¶(?<-4>.)*(?(4)(?!)))#
$1$5$2#$6 
s`U.*

(a|d)\1\1?
$1
ss
s
ww
w

Спробуйте в Інтернеті!Якби я бачив це запитання, коли воно було розміщене спочатку, це, мабуть, відповідь, яку я би дав, тому я все-таки публікую його, хоча відповідь у Retina є набагато кращою. Пояснення:

T` `+`^.*| ?¶.|.*$

Заповніть кордон. Це дозволяє уникнути прогулянки по лабіринту (наприклад, для тестового випадку 7).

I
#

Помістіть неабетковий маркер біля входу.

{+` (\w)
d$1
+`(\w) 
$1a
+`(¶(.)*) (.*¶(?<-2>.)*(?(2)(?!))\w)
$1s$3
}+m`(^(.)*\w.*¶(?<-2>.)*(?(2)(?!))) 
$1w

Затоплення заливається від виходу до входу. На кожному кроці використовуйте букву, щоб вказати найкращий напрямок руху (wasd - це може бути знайоме геймерам; я також вважав hjkl, але я вважав це занадто заплутаним). Крім того, віддайте перевагу повторювати той же напрямок; це дозволяє уникнути руху ліворуч / праворуч між двома вертикально розташованими клітинами.

^
w¶

Припустимо, перший крок - вниз.

w((.|¶)*(¶(.)*#.*¶(?<-4>.)*(?(4)(?!))(s)|#(d)|(a)#))
$4$5$6¶$1

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

{`^(.*d)(¶(.|¶)*)#(\w)
$1$4$2 #
^(.*a)(¶(.|¶)*)(\w)#
$1$4$2# 
^(.*s)(¶(.|¶)*¶(.)*)#(.*¶(?<-4>.)*(?(4)(?!)))(\w)
$1$6$2 $5#
}`^(.*w)(¶(.|¶)*¶(.)*)(\w)(.*¶(?<-4>.)*(?(4)(?!)))#
$1$5$2#$6 

Перемістіть маркер у напрямку останнього руху, прочитавши напрямок наступного руху від квадрата, до якого рухається маркер, і додайте його до списку напрямків. Це повторюється до початкуU буде досягнуто значення.

s`U.*

Видаліть усе після вказівки, оскільки це вже не потрібно.

(a|d)\1\1?
$1
ss
s
ww
w

Оригінальна сітка розміщена на макеті 3 × 2. Під час руху вертикально, якщо ми будемо зигзагувати по горизонталі, заливка буде оптимізувати рух і переміщувати лише 3n-1 символи по горизонталі, тому, розділяючи на три, нам потрібно округлювати. По вертикалі ми просто ділимо на 2.

Я також досліджував справжнє рішення квадратної сітки, тобто там, де матриця символів сама по собі квадрат, а не 3 × 2 макет з необов'язковою рамкою. Хоча, ймовірно, не відповідає питанню, можливість перенесення зменшила кількість байтів до 350: Спробуйте в Інтернеті!


Приємна відповідь, +1! Я бачу, що у вашому TIO-посиланні ви додали два -символи входу та виходу. Оскільки завдання в основному полягає в тому, щоб пройти лабіринт, я думаю, це добре, але мені цікаво: які були проблеми, коли ви не розміщували ці стіни над / під Iі під U? Крім того, чи можете ви перевірити, чи працює це для тестового випадку 7 із Iта Uу верхній частині замість боків? TIO перевищує межу 60 секунд, тому я не можу сам перевірити його. Незважаючи на те, що читаю ваше пояснення про те, що спершу намагаюся зійти за замовчуванням, я вважаю, що це має спрацювати нормально.
Kevin Cruijssen

@KevinCruijssen "Вторинна" відповідь працює для тестового випадку 7, але потрібні додаткові символи: Спробуйте в Інтернеті! продовження ...
Ніл

@KevinCruijssen "Основна" відповідь мала помилку, завдяки якій вона взагалі не могла впоратися з виходом на верхній рядок. Він також має схожий помилку на "вторинну" відповідь, завдяки чому він вважає за краще ходити за межами лабіринту, якщо зможе. (Крім того, я ніде не дійшов близько 60-секундної межі.)
Ніл

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