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


21

Змея должна заполнить любой лабиринт (пока он не застрянет).

Змея

Змея начинается в заданной начальной точке, указывая ВОСТОК . Он движется, всегда имея стену или часть своего тела сразу к ЛЕВОЙ своей головы (« последователь стены правила левой руки »), пока не застрянет, потому что все четыре направления вокруг его головы заняты. (Примечание: застрявшая змея не может заполнить все доступное пространство, но это не цель!)

Соревнование

Напишите программу или функцию, которая принимает лабиринт в качестве ввода в виде 2D-текста:

  • Ввод может быть в любом разумном формате: например, список строк, одна строка с символами новой строки, файл.
  • Лабиринт имеет стены (" #"), пустые места (" ") и ровно одну отправную точку (" 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
@ Иона: правильно. Существует единственный детерминированный путь, и он не оптимален. @ значение чернил: да. @ 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 server management studio, это покажет результат в виде текста.

Попробуйте онлайн


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 О, я думал, что это спасло немного, смеется. Также это довольно умно, спасибо!
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 . Теперь, когда я закончил с этим, я подумал, что, возможно, мне следовало бы вместо этого перенести решение Rod's Python 2, но я уже потратил слишком много времени на это.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.