Розв’яжіть цей Алькасар для мене


39

Нещодавно я грав у гру під назвою Alcazar. Це настільна гра-головоломка, де ваша мета - увійти з однієї двері, пройти через усі квадрати та вийти через інші двері. Єдині правила:

  • Введіть один раз, залиште один раз;
  • Пройдіть через усі квадрати;
  • Не проходьте через квадрат більше одного разу

На зображенні нижче показаний приклад дошки Алькасар і, з його правого боку, розгаданої головоломки (звичайно, це легко):

Зразок головоломки Алькасар

Ви можете знайти більше головоломок на веб- сайті http://www.theincrediblecompany.com/try-alcazar та завантажити гру в PlayStore (PS: Не реклама).

Моя проблема полягає в тому, що я майже закінчив гру, за винятком одного рівня. Я просто не можу знайти спосіб її вирішити. Отже, завдання, яке я пропоную: створити алгоритм, який вирішує будь-який нормальний 1 розв’язуваний 2 рівень Альказара.

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

╔═══════╗         ╔═══════╗
║▒ ▒ ▒ ▒║         ║┌─┐ ┌─┐║
║     ║ ║         ║│ │ │║│║
╣▒ ▒ ▒║▒╠         ╣│ └─┘║└╠
║ ══╦═╩═╣         ║│══╦═╩═╣
║▒ ▒║▒ ▒║         ║└─┐║┌─┐║
║   ║   ║   ==>   ║  │║│ │║
╣▒ ▒║▒ ▒║         ╣┐ │║│ │║
║ ║ ║   ║         ║│║│║│ │║
╣▒║▒ ▒ ▒║         ╣│║└─┘ │║
║ ║     ║         ║│║    │║
║▒ ▒ ▒ ▒║         ║└─────┘║
╚═══════╝         ╚═══════╝

На дошці вище розташовані клітинки, які потрібно заповнити.

Можна помітити, що між клітинами є вертикальний і горизонтальний затвор. Це тому, що мені довелося вставити проміжок між клітинками, щоб додати стіни. Це означає, що єдині важливі клітини - це ті, що вгорі, внизу, зліва та праворуч від кожної комірки. Діагоналі можна було видалити без втрати інформації. Наприклад, на дошці нижче обидва представляють одну і ту ж головоломку:

╔════╩╗         ═ ═ ╩ 
║▒ ▒ ▒║        ║▒ ▒ ▒║
║ ═══ ║           ═   
║▒ ▒ ▒║   ==   ║▒ ▒ ▒║
║     ║               
║▒ ▒ ▒║        ║▒ ▒ ▒║
╚╦════╝         ╦═ ══ 

Це справедливо і для рішень. Тобто підключати комірки не потрібно:

╔════╩╗        ╔════╩╗        ╔════╩╗
║▒ ▒ ▒║        ║┌───┘║        ║┌ ─ ┘║
║ ═══ ║        ║│═══ ║        ║ ═══ ║
║▒ ▒ ▒║   ==   ║└───┐║   =>   ║└ ─ ┐║
║     ║        ║    │║        ║     ║
║▒ ▒ ▒║        ║┌───┘║        ║┌ ─ ┘║
╚╦════╝        ╚╦════╝        ╚╦════╝

У наведеному вище прикладі обидва рішення означають однакове.

Так, тестові випадки. Ось вони:

Головоломка 1

╔════╩╗        ╔════╩╗
║▒ ▒ ▒║        ║┌ ─ ┘║
║ ═══ ║        ║ ═══ ║
║▒ ▒ ▒║   =>   ║└ ─ ┐║
║     ║        ║     ║
║▒ ▒ ▒║        ║┌ ─ ┘║
╚╦════╝        ╚╦════╝

Головоломка 2

╔═════╗        ╔═════╗
║▒ ▒ ▒║        ║┌ ─ ┐║
║   ║ ║        ║   ║ ║
╣▒ ▒║▒║        ╣└ ┐║│║
║ ║ ║ ║   =>   ║ ║ ║ ║
╣▒║▒ ▒╠        ╣┐║│ │╠
║ ║   ║        ║ ║   ║
║▒ ▒ ▒║        ║└ ┘ │║
╚════╦╝        ╚════╦╝

Головоломка 3

╔════╩══╗        ╔════╩══╗
║▒ ▒ ▒ ▒║        ║┌ ┐ └ ┐║
║ ║   ║ ║        ║ ║   ║ ║
╣▒║▒ ▒║▒╠        ╣┘║└ ┐║│╠
║ ╚══ ║ ║        ║ ╚══ ║ ║
║▒ ▒ ▒ ▒╠   =>   ║┌ ─ ┘ │╠
║   ═══ ║        ║   ═══ ║
║▒ ▒ ▒ ▒║        ║│ ┌ ┐ │║
║   ║   ║        ║   ║   ║
║▒ ▒║▒ ▒║        ║└ ┘║└ ┘║
╚═══╩═══╝        ╚═══╩═══╝

пазл 4

╔═══════╗        ╔═══════╗
║▒ ▒ ▒ ▒║        ║┌ ┐ ┌ ┐║
║     ║ ║        ║     ║ ║
╣▒ ▒ ▒║▒╠        ╣│ └ ┘║└╠
║ ══╦═╩═╣        ║ ══╦═╩═╣
║▒ ▒║▒ ▒║        ║└ ┐║┌ ┐║
║   ║   ║   =>   ║   ║   ║
╣▒ ▒║▒ ▒║        ╣┐ │║│ │║
║ ║ ║   ║        ║ ║ ║   ║
╣▒║▒ ▒ ▒║        ╣│║└ ┘ │║
║ ║     ║        ║ ║     ║
║▒ ▒ ▒ ▒║        ║└ ─ ─ ┘║
╚═══════╝        ╚═══════╝

Головоломка 5

╔══╩══════╗        ╔══╩══════╗
║▒ ▒ ▒ ▒ ▒║        ║┌ ─ ┐ ┌ ┐║
║   ║     ║        ║   ║     ║
║▒ ▒║▒ ▒ ▒╠        ║└ ┐║└ ┘ │╠
║   ╠════ ║        ║   ╠════ ║
║▒ ▒║▒ ▒ ▒║   =>   ║┌ ┘║┌ ─ ┘║
║   ║     ║        ║   ║     ║
║▒ ▒║▒ ▒ ▒╠        ║└ ┐║└ ─ ─╠
║   ╠═════╣        ║   ╠═════╣
║▒ ▒║▒ ▒ ▒║        ║┌ ┘║┌ ─ ┐║
║   ║     ║        ║   ║     ║
║▒ ▒ ▒ ▒ ▒║        ║└ ─ ┘ ┌ ┘║
╚══╦═══╦══╝        ╚══╦═══╦══╝

Головоломка 6

╔═══════════╗        ╔═══════════╗
║▒ ▒ ▒ ▒ ▒ ▒║        ║┌ ┐ ┌ ┐ ┌ ┐║
║           ║        ║           ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║│ └ ┘ └ ┘ │║
║       ═══ ║        ║       ═══ ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║└ ┐ ┌ ─ ─ ┘║
║     ═══   ║        ║     ═══   ║
╣▒ ▒ ▒ ▒ ▒ ▒╠   =>   ╣┐ │ │ ┌ ┐ ┌╠
║           ║        ║           ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║│ │ │ │ │ │║
║   ║   ║   ║        ║   ║   ║   ║
║▒ ▒║▒ ▒║▒ ▒║        ║│ │║│ │║│ │║
║   ║   ║   ║        ║   ║   ║   ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║└ ┘ └ ┘ └ ┘║
╚═══════════╝        ╚═══════════╝

Головоломка 7

╔════╩════════╦╩╗        ╔════╩════════╦╩╗
║▒ ▒ ▒ ▒ ▒ ▒ ▒║▒║        ║┌ ─ ─ ─ ─ ─ ┐║│║
║ ║       ║   ║ ║        ║ ║       ║   ║ ║
║▒║▒ ▒ ▒ ▒║▒ ▒ ▒║        ║│║┌ ─ ─ ┐║┌ ┘ │║
║ ║ ║ ═══ ║     ║        ║ ║ ║ ═══ ║     ║
║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒╠        ║│ │║┌ ─ ┘ └ ┐ │╠
║   ║           ║        ║   ║           ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║        ║│ │ └ ┐ ┌ ┐ └ ┘║
║     ║ ║     ══╣        ║     ║ ║     ══╣
║▒ ▒ ▒║▒║▒ ▒ ▒ ▒║        ║│ └ ┐║│║│ └ ─ ┐║
║     ║ ║       ║        ║     ║ ║       ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║        ║│ ┌ ┘ │ └ ┐ ┌ ┘║
║           ║ ══╣   =>   ║           ║ ══╣
║▒ ▒ ▒ ▒ ▒ ▒║▒ ▒║        ║└ ┘ ┌ ┘ ┌ ┘║└ ┐║
╠══       ║ ╚══ ║        ╠══       ║ ╚══ ║
║▒ ▒ ▒ ▒ ▒║▒ ▒ ▒║        ║┌ ┐ └ ┐ │║┌ ─ ┘║
║     ║ ║ ║     ║        ║     ║ ║ ║     ║
║▒ ▒ ▒║▒║▒ ▒ ▒ ▒║        ║│ └ ┐║│║│ └ ─ ┐║
║ ║   ║ ║ ╔══   ║        ║ ║   ║ ║ ╔══   ║
║▒║▒ ▒ ▒ ▒║▒ ▒ ▒║        ║│║┌ ┘ │ │║┌ ┐ │║
║ ║     ║ ║     ║        ║ ║     ║ ║     ║
║▒ ▒ ▒ ▒║▒ ▒ ▒ ▒║        ║│ └ ─ ┘║└ ┘ │ │║
║       ╚══     ║        ║       ╚══     ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║        ║└ ─ ─ ─ ─ ─ ┘ │║
╚════╦═╦═╦═════╦╝        ╚════╦═╦═╦═════╦╝

Головоломка 8 (Вибачте, я справді не маю рішення для цього)

╔══╩╦══╩═══╩═╩═╩═══╩╗
║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║
║   ║               ║
╣▒ ▒║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║
║   ╚══ ╔══     ╔═══╣
╣▒ ▒ ▒ ▒║▒ ▒ ▒ ▒║▒ ▒╠
║       ║   ╔══ ║   ║
╣▒ ▒ ▒ ▒ ▒ ▒║▒ ▒ ▒ ▒╠
║           ║       ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒╠
║           ║       ║
╣▒ ▒ ▒ ▒ ▒ ▒║▒ ▒ ▒ ▒╠
║   ╔═══╗   ╚══     ║
╣▒ ▒║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒║
║   ║   ║           ║
╣▒ ▒║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒╠
║ ══╝   ║       ╔══ ║
║▒ ▒ ▒ ▒║▒ ▒ ▒ ▒║▒ ▒║
║   ══╗ ╚══ ╔══ ║   ║
╣▒ ▒ ▒║▒ ▒ ▒║▒ ▒ ▒ ▒╠
║     ║     ║   ║   ║
╣▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║▒ ▒║
║   ═══   ══╗   ║   ║
╣▒ ▒ ▒ ▒ ▒ ▒║▒ ▒ ▒ ▒╠
╠══ ║       ║   ╔══ ║
║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒║▒ ▒╠
║   ╚══ ║   ║   ║   ║
╣▒ ▒ ▒ ▒║▒ ▒║▒ ▒ ▒ ▒╠
║       ║   ║       ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║
╚══╦═══╦═══╦═╦═╦═╦═╦╝

Вхідні дані

Введення коду може мати будь-яке представлення, якщо воно дотримується цих правил:

  1. Це повинен бути графічний ввід. Тому неможливо прочитати координатний список, наприклад.

  2. Горизонтальні стіни, вертикальні стіни та двері повинні бути чіткими, і вони повинні бути видимими (без порожніх символів).

  3. Банку можна замінити заготовками. Я просто використав інший символ, щоб виділити їх.

Вихідні дані

Вихід може також мати будь-яке представлення, якщо воно дотримується цих правил:

  1. Це повинен бути графічний вихід. Тобто можна побачити шлях, дивлячись на нього.

  2. Правило номер одне означає, що символи шляху мають бути різними. Тобто, буде щонайменше 6 символів шляху; горизонтальні, вертикальні та кутові.

  3. Щоб відповідь була вірною, вихід повинен бути такою ж дошкою, що і вхід (очевидно) з усіма заповненими осередками (на моє представлення ). Заповнення прогалин між клітинками необов’язкове.

Оцінка балів

Це , тому виграє найкоротший код у байтах.

1 Є деякі рівні Альказару, які мають необов'язкові комірки та тунелі. Вони не будуть розглядатися.

2 Є кілька дощок Алькасар, які неможливо.


2
Моя програма не знаходить рішення для головоломки 8. Ви впевнені, що це вирішимо? Може, якийсь друкарський помилок?
edc65

1
@ edc65 ж тут - рішення для №8
ngn

Відповіді:


5

Пітон 3 , 809 728 723 714 693 688 684 663 657 641 639 627 610 571 569 байт

Редагувати: Збережено 55 байт завдяки @Felipe Нарді Батісті

Не працює останній тестовий випадок за 60 секунд на TIO, але він повинен працювати правильно. Повертає список координат шляху. Близько 400 байтів використовуються для отримання списків даних з вводу-виводу.

A=enumerate
I,J="═║"
B=range
L=len
K=-1
Z=1,0
X=0,1
C=K,0
V=0,K
E=lambda a,b,p:(((a,b)in d)*L(p)==H*h)*p or max([E(q+a,w+b,p+[(q+a,w+b)])for q,w in y[a][b]if~-((q+a,w+b)in p)*-h>w+b>K<q+a<H]+[[]])
x=input().split("\n")
h=L(x[0])//2
H=L(x)//2
y=[[{C,Z,V,X}for i in B(h)]for j in B(H)]
d=[]
exec('d+=[(%s,i)for i,a in A(x[%s][1::2])if I<a]\nfor i,u in A(x[%s:%s:2]):\n d+=[(i,0)]*(J<u[0])+[(i,h-1)]*(J<u[K])\n for j,w in A(u[%s:%s:2]):\n  if"%s"==w:y[i][j]-={%s};y[i+%s][j+%s]-={%s}\n'*2%(0,*X,"",2,K,J,X,*X,V,H-1,K,2,K,1,"",I,Z,*Z,C))
print(max(E(*D,[D])for D in d))

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


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

1
@PhelypeOleinik Я не думаю, що це дуже гарна система балів. Зберігати його в гольф-коп є кращим рішенням, але якщо ви дійсно шукаєте рішення, я впевнений, що це можна змінити, щоб бути більш ефективним.
caird coinheringaahing

@cairdcoinheringaahing Я розумію, що найелегантніше рішення - це триматись так, як є. Але алгоритм, на який потрібні "дні чи навіть місяці", щоб вирішити головоломку 8х12, якимось чином неефективний, ви не думаєте? Як я це бачу, алгоритм, який вирішує проблему за менший час, повинен бути винагороджений, навіть якщо він трохи довший.
Феліпе Олейник

3
@PhelypeOleinik "Ефективність" коду не має значення. Ви кинули нам виклик написати короткий код, і це є основою вашого завдання. Додавання швидкості, з якою програма працює до суміші, лише ускладнює речі без потреби, а також може бути використана для смішних балів. Спеціальні системи балів зазвичай не спрацьовують. Якщо ви хочете короткий код, поставте питання про код-гольф. Якщо ви хочете швидкого коду, поставте питання про найшвидший код. Намагатися змішати їх разом - це не дуже гарна ідея.
LyricLy

У вашому exec(...)рядку є п'ять нових рядків, представлених у вигляді \n5 * 2 = 10 байт. Використання рядка з потрійним цитуванням додасть 4 байти ( ...''...''...), але потім видалить 5 байт, оскільки фактичні символи нового рядка можуть бути використані. Загалом це могло б зберегти один байт.
Джонатан Фрех

5

APL (Dyalog Classic) , 319 байт

iNj←⍳1+n←×/N←⌊2÷⍨⍴a←⎕⋄e←↑⊃,/{(,~'#='∊⍨a[(⍵⌽⍳2)∘+¨2×⍳N+⍵=⍳2])/,2,/[⍵]⊃,[⍵]/n i n}¨⍳2
r←{e g c←⍵⋄d←+/j∘.=∊g⋄e⌿⍨←(≠/c[e])∧2>⌈/d[e]⋄n≡≢g:gj/⍨d=10≡≢e:02>⌊/d+D←+/j∘.=,e:0⋄u←,¯1↑e←e[⍒⌊/D[e];]⋄e↓⍨←¯1⋄0≢r←∇e(g⍪u)(c-(-/c[u])×c=c[⊃u]):r⋄∇e g c}e(0e)j
a[1+2×⍳N]←' ??┌?─┐┬?└│├┘┴┤┼'[2⊥(↑(⊂i),¨¨{⊖∘⍉⍣⍵⊢n⍪¯1↓⌽∘⍉⍣⍵⊢i}¨⍳4)∊↓r⍪⌽r]
a

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

Введення використовується =#F7LJ<>^v.замість ═║╔╗╚╝╣╠╩╦▒того, щоб вписатись у класичну шаблону .

Усі тестові випадки, крім останнього, проходять за кілька секунд.

Останній тест займає 47 хвилин на моєму комп’ютері і не дає рішення.

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


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

1
@PhelypeOleinik Так, це досить неохайний вичерпний пошук. Причина, що швидко знаходить існуючі рішення, полягає в тому, що вона спробує спочатку скоріше вірогідний випадок (з vs без певного краю у графіку - мій евристичний - мінус градусів двох вершин, нижча - імовірніше). Причина, яку вона робить жахливо в останньому випадку, полягає в тому, що вона перевіряє всі можливості в будь-якому випадку і підрізає рекурсію лише на очевидних суперечностях. Здається, невідомі хороші алгоритми гамільтонового шляху, навіть для особливого випадку графіків обмеженого ступеня (≤4 сусідів).
ngn

3

JavaScript (ES6), 274 байти

Введіть як рядковий рядок, кожен рядок закінчується символом нового рядка. Двері позначені символом "2"

Виводиться як багаторядковий рядок із контуром, позначеним символом '1', дуже легко помітити.

Це глибинний перший пошук , який намагається пройти всі шляхи та відхилити, коли застряг. Це зовсім не ефективно, але може розгадувати загадки 1 .. 6 менш ніж за 1 хвилину.

z=>(w=z.search`
`+1,t=(w-2)*(z.length/w-1)/4,z=[...z],R=(p,l,q)=>[1,-1,w,-w].some(d=>l<t?z[q=p+d]<1&z[q+d]<1&&(R(q+d,++z[q]+l)||--z[q]):z[p+d]>1&&--z[p+d],++z[p])||--z[p],z.some((c,i)=>-c&&(x=i%w,R(i<w?i+w:x?x>w-3?i-1:i-w:i+1,--z[i])||++z[i]*0))&&z.join``.replace(/0/g,' '))

Менше гольфу

z => (
  w = z.search`\n`+1, // board width and offset to next row
  t = (w-2)*(z.length/w-1)/4, // total size of board, number of cells that must be filled
  z = [...z], // convert string to array
  d = [1, -1, w, -w], // delta to next position in all directions
  // recursive search
  // given a current position, try to move in all directions
  // if the board is not full, look for an emoty cell
  // if the board is full, look for a door
  R = (p, // current position
       l, // fill level
       q  // parameter used as a local variable
      ) => (
        ++z[p], // mark current position
        // .some will terminate early if the called function returns true
        // in case of return true the recursive function returns all way up leaving the path marked
        // in case of return false we need to unmark path and backtrack
        d.some( d => // for each direction, offset in d
          l < t // check if board is full
          ? z[q=p+d] < 1 & z[q+d] < 1 // not full, try to advance 
            && (++z[q], // mark intermediate cell
                R(q+d, 1+l) // recursive call incrementing fill level
                || --z[q] // if R return false, backtrack: unmark intermediate cell
               )
          : z[p+d] > 1 && --z[p+d]
        ) // full, ok only if I find a door nearby
        || --z[p], // if some returns false, unmark and backtrak
  // look for doors and for each door call R 
  // when R returns true, stop and return the marked board
  // if R returns false for each door, no solution, return false
  z.some((c,i) => 
   -c && // if numeric and != 0
    (x = i%w,
     z[i]=1, // marking starting position (door)
     R(i<w ? i+w : x ? x > w-3 ? i-1 : i-w : i+1, 1)
     || (z[i] = 2, false) // if R returned false, unmark a return false
    ) 
  ) && z.join``.replace(/0/g,' ') 
)

Усередині фрагмента тесту є рішення, що використовує DFS з деяким обмеженням, яке вирішує пазл 7 менше ніж за хвилину (на моєму ПК). Головоломка 8 не має рішення. Обмеження:

  • Усі порожні комірки повинні бути доступні від поточної комірки - порожній простір не повинен бути розділений на дві частини
  • Мають бути доступні двері
  • Конфігурацію комірок неможливо дослідити більше одного разу
  • Не можна пропустити клітинку, у якій є лише одна порожня сусідня комірка

Тест

Остерігайтеся, головоломка 7 значно перевищує час очікування виконання javascript у будь-якому браузері (використовуючи короткий і повільний вирішувач)

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