Наповніть лабіринт зміїною стіною, поки вона не застрягне


21

Зробіть, щоб змія заповнювала будь-який лабіринт (поки він не застряг).

Змія

Змія починається з заданої початкової точки, вказуючи СХІД . Вона рухається, завжди маючи стіну або частину її тіла відразу до ЛІВОРУЧ його голови ( « ліва стіна правило повторювача »), поки він не застряє , тому що всі чотири сторони навколо його голови зайняті. (Примітка: застрягла змія, можливо, не може заповнити весь доступний простір, але це не мета!)

Змагання

Напишіть програму або функцію, яка приймає лабіринт як вхід у вигляді двовимірного тексту:

  • Вхід може бути у будь-якому розумному форматі: наприклад, список рядків, одна рядок з новими рядками, файл.
  • У лабіринті є стіни (" #"), порожні місця (" ") і рівно одна відправна точка (" o").
  • Ви можете вибрати

    • або припустити, що перший і останній ряд і стовпець повністю є стінами;
    • або припустимо, що кожен вхід вважається неявним зовнішнім шаром стін
  • Ви можете припустити, що початковою точкою є стіна (або неявна стіна) безпосередньо над нею (Північ) і що змія може зробити дійсний вихідний хід у напрямку СХІД чи ПІВНЯ.

  • Ви можете припустити, що в тексті немає інших символів (крім нових рядків, якщо вони потрібні для вашого введення).
  • Можна припустити, що всі лінії однакової довжини.

і друкує / повертає "заповнений лабіринт" як вихід, із знімком змії в той момент, коли вона застрягла :

  • Тіло змії представлено символами, які >v<^вказують, де знаходиться її наступний відрізок
  • Початковою точкою змії є або її напрямок на старті (" >" якщо вона не повинна була повернутись негайно), або oхарактер (не потрібно бути послідовним)
  • Кінцева точка змії - oхарактер

Оцінка балів

Звичайний код гольфу: виграє найкоротший код

Приклад

in:
#################################
#                    o          #
#                               #
#     ##       ###       ##     #
#    ##     ##     ##     ##    #
#    ##     ##     ##     ##    #
#    ##      ##   ##      ##    #
#   ##       ##   ##       ##   #
#   ##         ###         ##   #
#    ##       #####       ##    #
#    ##       #####       ##    #
#    ##        ###        ##    #
#     ##                 ##     #
#                               #
#                               #
#################################

out:
#################################
#>>>>>>>>>>>>>>>>>>>v>>>>>>>>>>v#
#^>>>>>>>>>>>>>>>>>v>>>>>>>>>>vv#
#^^   ##>>>>>>v###o>>>>>v##   vv#
#^^  ##>^   ##>>>>^##   >v##  vv#
#^^  ##^    ##     ##    v##  vv#
#^^  ##^     ##   ##     v##  vv#
#^^ ##>^     ##   ##     >v## vv#
#^^ ##^<       ###       v<## vv#
#^^  ##^      #####      v##  vv#
#^^  ##^      #####      v##  vv#
#^^  ##^<      ###      v<##  vv#
#^^   ##^<<<<<<<<<<<<<<<<##   vv#
#^^<<<<<<<<<<<<<<<<<<<<<<<<<<<<v#
#^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<#
#################################

Анімовані (для ілюстрації):

введіть тут опис зображення

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

введіть тут опис зображення

Дякуємо Джонатану Аллану за його підняття, а Драко18 за пояснювальний знімок вище.

Інші приклади

in:
####################
#               o# #  
#                ###
#                  #
#      ##          #
#                ###
####################

out:
####################
#>>>>>>>>>>>>>>vv# #
#^>>>>>>>>>>>>vvv###
#^^   v<<<o<<<<v>>v#
#^^<<<<##^<<<<<<v<<#
#^<<<<<<<<<<<<<<<###
####################
in:
####################
#         o    #####  
#              #####
#                  #
#                 ##
####################

out:
####################
#         >>>>v#####
#             v#####
#             >>>>o#
#                 ##
####################
in:
################
#o             #
#   ########## #
# #          # #
# #          # #
# #          # #
# #  #       # #
# #          # #
# #          # #
# #          # #
# ############ #
#              #
################

out:
################
#>>>>>>>>>>>>>v#
#>>v##########v#
#^#>>>>>>>>>v#v#
#^#>>>>>>>>vv#v#
#^#^>>>>>>vvv#v#
#^#^^#    vvv#v#
#^#^^o<<<<<vv#v#
#^#^^<<<<<<<v#v#
#^#^<<<<<<<<<#v#
#^############v#
#^<<<<<<<<<<<<<#
################

У прикладі GIF, коли він входить до шаблону, чому б він не повернувся назад, щоб заповнити інші частини порожніх пробілів? Однозначно можна було повернути ліворуч то вгору, то вліво, то вниз, то назад, але змія вибрала прямо вниз. Чи є мета заповнити змію якомога більше пробілів чи дотримуватися лише стратегії "повернути праворуч при зустрічі зі стіною та закінчитися, якщо повернути праворуч двічі"?
Чарівний восьминога Урна

2
@MagicOctopusUrn Я не впевнений, що розумію, в який момент ви бачите неоднозначність. Але, щоб відповісти на ваше запитання, мета - не заповнити якомога більше місця. Однак алгоритм ("послідовник стіни") - це не просто "повернути праворуч один раз або, якщо це неможливо, то два рази": якщо змія опиниться без стіни зліва, вона повинна буде повернути ліворуч (зберігаючи "ліворуч" руку "на стіні / на себе)
Нікола Сап

(вибачте, що я неправильно прочитав ваш алгоритм, що пройшов)
Нікола Сап

2
@ jonah: правильно. Є єдиний детермінований шлях і він не є оптимальним. @ значення чорнила: так. @ jonathanallan Я намагаюся бачити неоднозначність, але це може бути тільки я. Моя версія наступного настінного алгоритму: зберігайте свій напрямок, якщо у вас більше немає перешкод ліворуч [оцінюється спочатку], і в цьому випадку поверніть ліворуч, або ви потрапите на стіну [оцінюється друге], у цьому випадку поверніть праворуч по можливості, або гра закінчена.
Нікола Сап

1
Мені довелося розсікати gif, щоб зрозуміти, чому кінцевий стан був таким, яким він був. Це не видно з остаточного відображеного кадру, а скоріше зі стану: i.stack.imgur.com/kj67V.png Я сподіваюся, що це допомагає людям.
Draco18s

Відповіді:


8

Вугілля деревне , 94 68 байт

F²⊞υSW¬⁼§υ⁰§υ±¹⊞υS≔⪫υ¶θPθ…θ⌕θo≔⁰θW№KV «≧⁺⊖⌕E³§KV⁺θκ θ✳§rdluθ§>v<^θ»o

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

F²⊞υSW¬⁼§υ⁰§υ±¹⊞υS≔⪫υ¶θ

Розбийте введення в рядок. Цього можна уникнути, використовуючи менш зручний формат введення.

Pθ…θ⌕θo

Роздрукуйте вхід, не переміщуючи курсор, а потім надрукуйте ще oраз, щоб курсор опинився під ним.

≔⁰θ

Ініціалізуйте поточний напрямок.

W№KV «

Повторіть, поки ще є вільний простір в якомусь напрямку.

≧⁺⊖⌕E³§KV⁺θκ θ

Порахуйте, чи може змія повернути ліворуч, чи вона змушена повернути праворуч. Код ≦⊖θW¬⁼§KVθ ≦⊕θтакож працює для цього за тим самим підрахунком байтів, хоча він вважається 0вгору замість правильного, тому решту коду потрібно адаптувати.

✳§rdluθ§>v<^θ

Виведіть відповідний символ тіла у відповідному напрямку.

»o

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


7

Python 2 , 273 253 242 байт

-11 байт завдяки ArBo

g=input()
d=0
t=lambda g,k=1:'\n'.join(map(''.join,zip(*g.split('\n')[::k])[::-k]))
h='o '
while 1:
 l,r=t(g,-1),t(g)
 if h in l:g=l;d-=1
 elif h in g:g=g.replace(h,'>v<^'[d%4]+'o')
 elif h in r:g=r;d+=1
 else:break
exec-d%4*'g=t(g);'
print g

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

Це працює за допомогою пошуку рядка 'o 'та заміни його на '[>v<^]o', якщо він знаходиться в лабіринті.

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

Функція t=lambda g,k=1:'\n'.join(map(j,zip(*g.split('\n')[::k])[::-k]))використовується для обертання сітки


3

Желе , 72 56 байт

œṣ€⁾o j€ṛị“v<^>”;”oʋ,
UZ$ṛ¡+ƭ€Ɱ3r5¤ç/€ḟ$Ḣß$ṛ¹?
,0ÇZU$ṛ¡/

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

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

Рішення дещо натхнене методом, який використовується у відповіді @ Rod's Python 2 , хоча реалізація дуже відрізняється.



3

Запит T-SQL 2008, 373 371 366 байт

У мене був список пріоритетів, завжди ковзаючи ліворуч, прямо, праворуч. Я змінив цей пріоритет, щоб завжди ковзати назад, ліворуч, прямо, праворуч. Ковзання назад завжди буде заблоковано, тому пріоритет все одно той самий, окрім першого. Повертаючи змію спочатку вниз (C = 4), вона намагається зісковзнути вгору при заслінковуванні. Цей маленький трюк врятував мені 2 байти. Тому що мені не потрібно було додавати 1 до ~ - ~ -c% 4.

Я вставив 2 перерви рядка, щоб зробити його читабельним

DECLARE @ varchar(8000)=
'################
#o             #
#   ########## #
# #          # #
# #          # #
# #          # #
# #  #       # #
# #          # #
# #          # #
# #          # #
# ############ #
#              #
################';

WITH s as(SELECT 0i,4c,@ m 
UNION ALL
SELECT~-i,x,stuff(stuff(m,~-a+x/3*2+(x-3)%2*s,1,'o')
,a,1,char(59+x+~x%2*11*~x))FROM(SELECT
charindex(' ',replicate(stuff(substring(m,~-a,3),2,1,substring(m,a+~s,1))+
substring(m,a-~s,1)+'~',2),-~-~c%4)%5x,*FROM(SELECT*,charindex('o',m)a,charindex('
',M)S FROM S)Q)L
WHERE x>0)SELECT top 1m FROM s
ORDER BY i
OPTION(MAXRECURSION 0)

Мені довелося внести деякі незначні корективи, щоб виконати це в Інтернеті, опублікована версія працює в студії управління сервером MS-SQL.

Натисніть Ctrl-T перед виконанням в студії управління MS-SQL сервера, це покаже результат як текст.

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


2
Я не маю ідеї гортати, як це працює, але можу переконатися, що це працює. Дивовижна робота!
BradC

@BradC дякую за підтвердження та комплімент. Сьогодні рішення Sql не дуже люблять.
t-clausen.dk

1

Python 3 , 343 байт

import sys
X=0,1,0,-1
F,*Y=*X,0
L=3
g=[*map(list,sys.stdin.read().split("\n"))]
e=enumerate
r,c=[[r,c]for r,R in e(g)for c,C in e(R)if"o"==C][0]
while 1:
	if" "==g[r+X[L]][c+Y[L]]:F,L=L,~-L%4
	elif" "<g[r+X[F]][c+Y[F]]:
		if" "<g[r-X[L]][c-Y[L]]:g[r][c]="o";break
		L,F=F,-~F%4
	g[r][c]=">v<^"[F];r,c=r+X[F],c+Y[F]
for r in g:print("".join(r))

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

-11 байт завдяки ArBo
-4 байти завдяки Джонатану Фреху


Ви можете грати в гольф ініціалізацію X, Yі Fщоб , X=0,1,0,-1;F,*Y=*X,0якщо я не помиляюся. Крім того, import*витрати ви більше байтів, ніж економить.
ArBo

@ArBo О, я думав, що це економить щось lol. Також це досить розумно, дякую!
HyperNeutrino

Я думаю, ви можете зберегти байт за допомогою *g,=map(...). А чи sys.stdin.readlines()працює, можливо?
Андрас Дек

1
Крім того, ви можете, ймовірно, зберегти кілька байтів, припустивши однолінійне введення та використовуючи input().
Андрас Деак

1
if C=="o"~> if"o"==C, if g[r+X[L]][c+Y[L]]==" ", elif g[r+X[F]][c+Y[F]]>" ", if g[r-X[L]][c-Y[L]]>" "Відповідно.
Джонатан Фрех

1

05AB1E , 54 52 байти

[S¶¡øí3FDíø})J€»¼D¾èU¼.Δ.¼„o ©å}DÄiXqë®">^<v"¾è'o«.;

Введення / виведення як однорядний рядок.

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

[                      # Start an infinite loop:
 S                     #  Split the multi-line string into a list of characters
                       #  (which will use the implicit input in the first iteration)
  ¶¡                   #  Then split by newlines
    øí                 #  Rotate the matrix once clockwise
      3F               #  Loop 3 times:
        D              #   Create a copy of the matrix
         íø            #   And rotate this copy once counterclockwise
       })              #  After the loop: wrap all four matrices into a list
 J                     #  Join each inner-most character-list to string-lines again
  €»                   #  And join each inner list of lines by newlines again
    ¼                  #  Increase variable `c` by 1 (variable `c` is 0 by default)
     D¾<è              #  Index the updated variable `c` in a copy of the list of matrices
                       #  (note that indexing wraps around in 05AB1E)
         U             #  Pop and store it in variable `X`
    ¼                  #  Then increase variable `c` again
                     #  Find the first multi-line string in the list which is truthy for:
                     #   Decrease variable `c` by 1 first
        o             #   Push string "o "
           ©           #   Store this string in variable `®` (without popping)
            å          #   Check if the current multi-line string contains this "o "
    }D                 #  Duplicate the result (results in -1 if none were truthy/found)
      Äi               #  If no result was found:
        X              #   Push variable `X`
         q             #   And stop the program, after which this multi-line string of
                       #   variable `X` is output implicitly as result
       ë               #  Else:
         ">^<v"¾è      #   Get the `c`'th character in string ">^<v"
                       #   (note that indexing wraps around in 05AB1E)
                 'o«  '#   Append a trailing "o" to this character
        ®           .; #   And replace the first variable `®` ("o ") in the 
                       #   multi-line string with this

0

Pyth , 161 байт

J.zK[Z1Z_1)=Y+tKZVlJFTl@JNIq@@JNT\oA[NT;=N3=TZ#Iq@@J+G@KN+H@YNd=TN=N%tN4.?In@@J+G@KT+H@YTdIn@@J-G@KN-H@YNd XJGX@JGH\oB=NT=T%hT4)) XJGX@JGH@">v<^"TA(+G@KT+H@YT;jJ

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

Порт HyperNeutrino на Python 3 . Тепер, коли я з цим закінчуюсь, я думаю, що, можливо, мені слід було б перенести рішення Python 2 Rod, але я вже витратив надто багато часу на це.

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