Encha o labirinto com uma serpente que segue a parede até ficar presa

21

Faça uma cobra encher qualquer labirinto (até ficar preso).

A cobra

A cobra começa em um determinado ponto de partida, apontando para o LESTE . Ele se move sempre tendo uma parede ou parte de seu corpo imediatamente à esquerda de sua cabeça (" seguidor de parede da regra da esquerda "), até ficar preso porque todas as quatro direções ao redor de sua cabeça estão ocupadas. (Nota: uma cobra presa pode não preencher todo o espaço acessível, mas esse não é o objetivo!)

O desafio

Escreva um programa ou função que aceite um labirinto como entrada na forma de um texto 2D:

  • A entrada pode estar em qualquer formato razoável: por exemplo, uma lista de strings, uma única string com novas linhas, um arquivo.
  • O labirinto possui paredes (" #"), espaços vazios (" ") e exatamente um ponto de partida (" o").
  • Você pode optar por

    • ou suponha que a primeira e a última linha e coluna sejam inteiramente paredes;
    • ou assumir que toda entrada é considerada como tendo uma camada externa implícita de paredes
  • Você pode supor que o ponto inicial tenha uma parede (ou uma parede implícita) diretamente acima dela (NORTE) e que a cobra possa fazer um movimento inicial válido na direção LESTE ou SUL.

  • Você pode supor que nenhum outro caractere esteja presente no texto (exceto novas linhas, se sua entrada precisar deles).
  • Você pode assumir que todas as linhas têm o mesmo comprimento.

e imprime / retorna um "labirinto preenchido" como saída, com um instantâneo da cobra no momento em que ficou presa :

  • O corpo da cobra é representado pelos caracteres >v<^apontando para onde seu próximo segmento é
  • O ponto de partida da cobra é sua direção no início (" >" a menos que tenha que virar imediatamente) ou um opersonagem (não precisa ser consistente)
  • O ponto final da cobra é um opersonagem

Pontuação

Código habitual de golfe: o código mais curto vence

Exemplo

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#
#^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<#
#################################

Animado (para fins ilustrativos):

insira a descrição da imagem aqui

Edit: note que, em caso de dúvida, a cobra deve "manter a mão esquerda" na parede que já está, seguindo os cantos, sem pular para uma parede a 1 quarteirão de distância.

insira a descrição da imagem aqui

Agradeço a Jonathan Allan por mencioná-lo e a Draco18s pelo instantâneo explicativo acima.

Outros exemplos

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#
#^<<<<<<<<<<<<<#
################
Nicola Sap
fonte
No exemplo do GIF, quando entra no padrão, por que não volta a preencher as outras partes dos espaços vazios? Definitivamente, era possível virar à esquerda, depois para cima, para a esquerda e para baixo, e depois para trás, mas a cobra preferia a direita. O objetivo é preencher o maior número possível de espaços com a cobra ou seguir apenas a estratégia "virar à direita ao encontrar um muro e terminar se virar duas vezes à direita"?
Magic Octopus Urn
2
@MagicOctopusUrn Não sei ao certo em que ponto você vê a ambiguidade. Mas, para responder à sua pergunta, o objetivo não é preencher o máximo de espaço possível. No entanto, o algoritmo ("seguidor de parede") não é apenas "vire à direita uma vez ou, se não for possível, duas vezes": se a cobra se encontrar sem uma parede à esquerda, terá que virar à esquerda (mantendo a tecla "esquerda mão "na parede / em si)
Nicola Sap
(desculpe, eu li errado o resumo do seu algoritmo)
Nicola Sap
2
@ Jonas: correto. Existe um único caminho determinístico e não é o ideal. @ tinta valor: sim. @ Jonathanallan Eu luto para ver a ambiguidade, mas pode ser apenas eu. Minha versão do algoritmo de parede a seguir é: mantenha sua direção, a menos que você não tenha mais um obstáculo à sua esquerda [avaliado primeiro]; nesse caso, vire à esquerda ou você atinja uma parede [avaliado em segundo]; nesse caso, vire à direita se possível, ou fim de jogo.
Nicola Sap
1
Eu tive que dissecar o gif para descobrir por que o estado final era do jeito que era. Não é aparente no quadro final exibido, mas no estado anterior: i.stack.imgur.com/kj67V.png Espero que ajude as pessoas.
Draco18s 19/06

Respostas:

8

Carvão , 94 68 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

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

Coloque a entrada em uma sequência. Isso pode ser evitado usando um formato de entrada menos conveniente.

Pθ…θ⌕θo

Imprima a entrada sem mover o cursor e, em seguida, imprima onovamente, para que o cursor fique embaixo dela.

≔⁰θ

Inicialize a direção atual.

W№KV «

Repita enquanto ainda houver um espaço livre em alguma direção.

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

Calcule se a cobra pode virar à esquerda ou se é forçada a virar à direita. O código ≦⊖θW¬⁼§KVθ ≦⊕θtambém funciona para isso na mesma contagem de bytes, embora seja considerado 0ativo, em vez de correto, portanto, o restante do código precisa ser adaptado.

✳§rdluθ§>v<^θ

Emita o caractere do corpo apropriado na direção apropriada.

»o

Restaure a cabeça. Isso também pode ser escrito como Poimprimir a cabeça sem mover o cursor a cada passagem pelo loop (mas isso permite que o loop seja implicitamente fechado para a mesma contagem de bytes).

Neil
fonte
7

Python 2 , 273 253 242 bytes

-11 bytes graças ao 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

Experimente online!

Isso funciona pesquisando a string 'o 'e substituindo-a por '[>v<^]o', se estiver no labirinto.

A mesma verificação também será feita no labirinto girado, imprimindo o labirinto preenchido quando a sequência não estiver mais lá.

A função t=lambda g,k=1:'\n'.join(map(j,zip(*g.split('\n')[::k])[::-k]))é usada para girar a grade

Cajado
fonte
3

Geléia , 72 56 bytes

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

Experimente online!

Um programa completo que recebe a entrada como uma lista de cadeias e retorna uma lista de cadeias com a cobra final. Observe que o rodapé no TIO converte uma única sequência separada de nova linha na entrada desejada e restaura as novas linhas no final; isso é apenas por conveniência.

Solução um pouco inspirada no método usado pela resposta do @ Rod's Python 2 , embora a implementação seja muito diferente.

Nick Kennedy
fonte
3

Rubi , 126 118 bytes

-8 bytes salvos abusando em +=vez de procurar manualmenteo novamente após reposicioná-lo.

->s{d=[q=1,1+l=s=~/$/,-1,~l];i=s=~/o/;(s[i]=">v<^"[q];s[i+=d[q]]=?o)while q=[~-q%4,q,-~q%4].find{|e|s[i+d[e]]==' '};s}

Experimente online!

Value Ink
fonte
3

Consulta T-SQL 2008, 373 371 366 bytes

Eu tinha uma lista de prioridades, sempre deslize para a esquerda, reta, direita. Mudei essa prioridade para sempre deslizar para trás, esquerda, reta, direita. O deslizar para trás sempre será bloqueado, portanto a prioridade ainda é a mesma, exceto o primeiro deslizamento. Ao abaixar a cobra inicialmente (C = 4), ela tenta deslizar para cima quando desliza para trás. Esse pequeno golpe me salvou 2 bytes. Porque eu não precisei adicionar 1 a ~ - ~ -c% 4.

Inseri duas quebras de linha para torná-lo legível

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)

Eu tive que fazer alguns pequenos ajustes para executar isso online, a versão postada é executada no estúdio de gerenciamento do servidor MS-SQL.

Pressione Ctrl-T antes de executar no estúdio de gerenciamento do servidor MS-SQL; isso mostrará o resultado como texto.

Experimente online

t-clausen.dk
fonte
2
Não faço ideia de como isso funciona, mas posso verificar se funciona. Trabalho incrível!
BradC 17/06
@BradC, obrigado pela confirmação e pelo elogio. Atualmente, as soluções SQL não recebem muito amor.
t-clausen.dk 18/06
1

Python 3 , 343 bytes

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))

Experimente online!

-11 bytes graças ao ArBo
-4 bytes graças a Jonathan Frech

HyperNeutrino
fonte
Você pode golfe a inicialização de X, Ye Fpara X=0,1,0,-1;F,*Y=*X,0, se não estou enganado. Além disso, import*custa mais bytes do que economiza.
ArBo 14/06
@ ArBo Oh, eu pensei que estava economizando algumas lol. Também isso é muito inteligente, obrigado!
HyperNeutrino 14/06
Eu acho que você pode salvar um byte com *g,=map(...). E sys.stdin.readlines()funciona talvez?
Andras Deak
1
Como alternativa, você provavelmente pode salvar alguns bytes assumindo uma entrada de linha única e usando input().
Andras Deak 14/06
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]]>" "Em conformidade.
Jonathan Frech
1

05AB1E , 54 52 bytes

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

E / S como uma única sequência de várias linhas.

Experimente online ou verifique todos os casos de teste .

Explicaçã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
Kevin Cruijssen
fonte
0

Pitão , 161 bytes

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

Experimente online!

Porto da solução Python 3 do HyperNeutrino . Agora que terminei, estou pensando que talvez eu devesse ter portado a solução Python 2 do Rod, mas já gastei muito tempo nisso.

randomdude999
fonte