Renderizar um labirinto ASCII

18

Veja! É um labirinto ASCII! Soo coolzors, amazeballs e outras coisas.

+-+-----+---+
| |     |   |
| |  ++   | |
| |  ++ +-+ |
|       |   |
+-------+ | |
|         | |
+---------+-+

Mas, mas, mas ... é doloroso descobrir em que direção todas as partes do labirinto estão indo. Eu só quero desenhar o layout e o labirinto tornar-se mais suave sem muito tempo.

E se eu pudesse desenhar isso em ...

#############
# #     #   #
# #  ##   # #
# #  ## ### #
#       #   #
######### # #
#         # #
#############

Isso seria tão doce!


As regras (como as regras são resfriadas):

  • Escreva um código para converter uma string em um labirinto ascii e produza o resultado.
  • Qualquer caractere que não seja um espaço em branco será lido como uma parede.
  • Cada caractere de parede decidirá qual personagem basear-se em seus vizinhos (apenas nas direções norte, sul, leste e oeste).
    • Se um caractere não tiver vizinhos que não sejam espaços em branco, será um sinal de mais (+).
    • Se um caractere tiver vizinhos nas direções vertical (Norte-Sul) e horizontal (Leste-Oeste), será um sinal de adição (+).
    • Se um caractere tiver vizinhos apenas na direção vertical (Norte-Sul), será um símbolo de barra vertical (|).
    • Se um caractere tiver vizinhos apenas na direção horizontal (Leste-Oeste), será um sinal de menos (-).
  • A entrada pode ser uma única sequência (com linhas separadas por caracteres de nova linha ou uma matriz de sequências).
  • Todos os caracteres de entrada serão caracteres ASCII imprimíveis; você não precisa lidar com conjuntos de caracteres estendidos.
  • Use qualquer idioma antigo, por favor.
  • Se houver espaço em branco antes de uma linha, deve ser a mesma quantidade em cada linha. Qualquer espaço em branco após cada linha de saída é bom.
  • Tente resolvê-lo com o menor número de bytes.

Casos de teste:

1: Quadro

Entrada:

##########
#        #
#        #
#        #
##########

Resultado:

+--------+
|        |
|        |
|        |
+--------+

2: Labirinto clássico

Entrada:

#################
        #       #
# ##### # ##### #
#   # # #     # #
# # # # ##### # #
#   # #       # # 
### # ####### # #
#   # #    #  # # 
# ### # ## # ##
#     # ##    #  
#################

Resultado:

--------+-------+
        |       |
| --+-+ | ----+ |
|   | | |     | |
| + | | +---- | |
|   | |       | | 
+-- | +----+- | |
|   | |    |  | | 
| --+ | ++ | -+
|     | ++    |  
+-----+-++----+--

3: Ovos verdes, cara.

Entrada:

I do not like green eggs and ham.
I do not like them, sam I am.
Would you like them here or there?
I would not like them anywhere!

Resultado:

| ++ +++ ++++ +++++ +++- -++ ----
| ++ +++ ++++ +++++ +++ + +++
+-+++ +++ ++++ ++++ ++++ ++ +++---
| +++-+ +++ ++++ ++-+ +++++++++

4: Sincelos

Entrada:

Word Icicle!
Word Icicle 
Word  cicle 
 ord  cicle 
 ord   icle 
 ord   i le 
 or    i le 
 or    i l  
 or      l  
 or         
  r         

Resultado:

++++ ++++++-
++++ ++++++ 
++++  +++++ 
 +++  +++++ 
 +++   ++++ 
 +++   | ++ 
 ++    | ++ 
 ++    | |  
 ++      |  
 ++         
  |         
AJFaraday
fonte
1
A terceira linha de ovos verdes e presunto não deveria terminar ---?
precisa saber é o seguinte
1
Os resultados para vizinhos mistos ainda não estão claros; não sei por que os pingentes de gelo teriam algum -s ou por que o labirinto clássico não tem quatro +s na linha inferior.
194 Neil
1
podemos aceitar a entrada como um quadrado preenchido com espaços (ou seja, matriz)? É permitido que a saída tenha espaço em branco extra em torno dela? Além disso, você realmente quer dizer smallest number of characters, não bytes?
Dzaima 16/04
1
Eu acho que 1) o labirinto clássico deve ter um +no meio da 1ª linha 2) o !dos sincelos deve ser substituído por um -. Você poderia verificar esses dois?
Arnauld #
1
Por whitespace, você simplesmente não significa apenas espaço? Eu não quero ter que guias de apoio e você provavelmente não quer me transformar novas linhas quer
Jo rei

Respostas:

11

APL (Dyalog Unicode) , 57 35 bytes SBCS

–22 graças a uma nova solução da ngn .

Função tácita anônima tomando uma matriz de caracteres como argumento.

{⊃'+-|+'↓⍨25 4 2⊃¨⊂⍱∘⌽⍨' '≠,⍵}⌺3 3

Experimente online!

{}⌺3 3 Em cada bairro 3 por 3, aplique a seguinte função:

,⍵ ravel (achatar)

' '≠ Booleano onde não espaço

⍱∘⌽⍨ que NOR é inversa (incl. nem NOR superior inferior, nem esquerda NOR direita)

5 4 2⊃¨⊂escolha o , e elemento da lista inteira,
  ou seja, eu vazio, sem vertical, sem horizontal

2⊥ avalie na base 2 (binária)
  ou seja, ≥4: eu vazio; 3: sem vizinhos; 2: sem vizinhos horizontais; 1: não vertical; 0: tem ambos

'+-|+'↓⍨ solte muitos elementos dessa string
  ou seja auto vazio: ; sozinho +:; vizinho vertical (s) de: |+; horizontal -|+:; ambos:+-|+

 escolha o primeiro elemento (use espaço se não houver)
  ou seja auto vazio: ; sozinho +:; vizinho vertical (s) de: |; horizontal -:; ambos:+


Solução antiga

Função tácita anônima tomando uma matriz de caracteres como argumento.

{' +-|+'⊃⍨1⍳⍨(' '=5⊃,⍵),(∧/,⊢)∨/2 21' '≠(90 1)/,⍵}⌺3 3

Experimente online!

{...}⌺3 3 Em cada bairro 3 por 3, aplique a seguinte função:

,⍵ ravel (achatar)

(...)/  Filtre usando a seguinte máscara:

  9⍴0 1 remodelar ciclicamente [0,1] para o comprimento 9 (seleciona N, W, E, S)

' '≠ Booleano onde não espaço

1⌽ gire um passo para a esquerda; [W,E,S,N]

2 2⍴ remodelar para matriz 2 por 2; [[W,E],[S,N]]

∨/ redução OR em linha: [horizontal,vertical]

(...)  Aplique a seguinte função tácita:

   a identidade; [horizontal,vertical]

  ∧/, precedido por sua redução AND; [both,horizontal,vertical]

(), Acrescente o seguinte:

  ,⍵ percorrer (achatar) o bairro

  5⊃ escolha o elemento (ele mesmo)

  ' '= Booleano se espaço (ou seja, vazio)

 Agora temos [empty,both,horizontal,vertical]

1⍳⍨ índice de 1 à esquerda (fornece 5 se não houver vizinhos)

' +-|+'⊃⍨ use isso para escolher o símbolo

   

Adão
fonte
6

JavaScript (ES6), 110 bytes

Formato de E / S: matriz de cadeias.

a=>a.map((s,y)=>s.replace(/\S/g,(_,x)=>'+|-+'[[-1,p=0,1,2].map(c=>p|=(a[y+c%2]||0)[x+~-c%2]>' '?c&1||2:0)|p]))

Experimente online!

Ou 108 bytes usando uma matriz de caracteres.

Arnauld
fonte
6

Python 2 , 181 168 bytes

graças a Freira Furada por -13 bytes

m=input()
f=lambda x,y:(['']+m+[''])[y+1][x:x+1]>' '
print[[(c<'!')*' 'or'+-|+'[f(x+1,y)|f(x-1,y)|2*f(x,y+1)|2*f(x,y-1)]for x,c in enumerate(r)]for y,r in enumerate(m)]

Experimente online!

ovs
fonte
5

MATLAB, 113 110 101 bytes

function F(A)
B=A>32
c=[1 1 1]
f=@(c)conv2(B,c,'s')>1
h=f(c)
v=f(c')
char((13*h+92*v-94*(h&v)).*B+32)

Converte a entrada em lógica, aplica convolução em horizontal e vertical e combina as saídas para criar os caracteres correspondentes.

3 bytes salvos pelo @Adriaan por me dizer que você pode obstruir a saída no PPCG: P

9 bytes salvos graças a inúmeros comentários @flawr!

Brain Guider
fonte
2

Retina 0.8.2 , 92 bytes

\S
0
(?<=(.)*)0(?=(?>.*\n(?<-1>.)*)0)|0(?=(.)*)(?<=0(?>(?<-2>.)*\n.*))
1
T`d`+|`\b.\b
T`d`-+

Experimente online! Requer entrada retangular. O link inclui casos de teste. Explicação:

\S
0

Altere todos os não espaços para 0s.

(?<=(.)*)0(?=(?>.*\n(?<-1>.)*)0)|0(?=(.)*)(?<=0(?>(?<-2>.)*\n.*))
1

Procure todos os 0s com outro 0imediatamente acima ou abaixo na mesma coluna e altere-os para 1. Os 1s agora são os locais com vizinhos verticais, enquanto 0s não têm vizinhos verticais.

T`d`+|`\b.\b

Procure todos os dígitos sem vizinhos horizontais. Os 0s também não têm vizinhos verticais, então eles se tornam +s, enquanto os 1s têm vizinhos verticais, então eles se tornam |s.

T`d`-+

Os dígitos restantes têm vizinhos horizontais. Os 1s também têm vizinhos verticais, então eles se tornam +s, enquanto os 0apenas têm vizinhos horizontais, então eles se tornam -s.

Neil
fonte
1

Python 3 , 336 bytes

def g(s):
 h,j,s=' +|-+','',s.splitlines()
 s+=['']
 for n in range(len(s)):
  s[n]+=' '
  for i in range(len(s[n])-1):
   l,r,k=s[n][i-1],s[n][i+1],0
   try:u=s[n-1][i]
   except:u=' '
   try:d=s[n+1][i]
   except:d=' '
   if not s[n][i]==' ':
    k+=1
    if not u==d==' ':k+=1
    if not l==r==' ':k+=2
   j+=h[k]
  j+='\n'
 print(j)

Experimente online!

Eu tive que usar muito código para lidar com erros de maiúsculas e minúsculas.

akozi
fonte
1

C (gcc) , 143 bytes

char**y,*z,h,v;f(char**x){for(y=x;*y;++y)for(z=*y;*z;++z)if(*z-32){h=z[1]-32|z[-1]-32;v=y[1][z-*y]-32|y[-1][z-*y]-32;*z=h?v?43:45:(v?'|':43);}}

Experimente online!

A função f modifica uma matriz de seqüências de caracteres no local. A área ao redor da matriz deve ser preenchida com espaços (um pouco restrito). Mesmo que isso não atenda exatamente aos requisitos que a maioria das soluções está usando, ele estará em conformidade com as regras se dissermos que representamos uma nova linha com dois espaços (e pegamos uma série de cadeias terminando em novas linhas).

Ungolfed

f(char**x){
    char **y;
    for (y = x; *y; ++y) {
        char *z;
        for (z = *y; *z; ++z) {
            if (*z != ' ') {
                if (z[1] != ' ' || z[-1] != ' ') {
                    // Horizontal exists
                    if (y[1][z-*y] != ' ' || y[-1][z-*y] != ' ')
                        // Vertical exists
                        *z = '+';
                    else
                        *z = '-';
                } else {
                    // Horizontal doesn't exist
                    if (y[1][z-*y] != ' ' || y[-1][z-*y] != ' ')
                        // Vertical exists
                        *z = '|';
                    else
                        *z = '+';
                }
            }
        }
    }
}

Este foi um desafio divertido da aritmética dos ponteiros. Usando a iteração do ponteiro no estilo C, é fácil obter os vizinhos horizontais, mas os verticais eram mais difíceis. Felizmente, o ponteiro y ainda está por aí (o que aponta para o valor inicial de z), para que eu possa deduzir meu índice e usá-lo para acessar o mesmo elemento em uma linha diferente. Parecia uma escrita muito errada y[-1][z-*y], pois voava diante de qualquer estilo razoável!

LambdaBeta
fonte
120 bytes
ceilingcat 07/07