Etiquetar callejones sin salida


16

Dada una entrada de un "camino" de arte ASCII, da salida al camino con todos los callejones sin salida etiquetados.

Este es un camino:

########.....######..#..###
#......#######....#..#..#.#
#.##......#...#####..#..###
#..#####..#....#..#######.#
#......#...#####.....##...#
#..###.#...#...###...#..###
##########.#..#..##..#.##.#
..#......#.######.#..#.#.#.
..#......#.#..#.#.#..#.#.#.
..######.###..##..#########

Este es el camino con callejones sin salida etiquetados con la letra X:

########.....######..X..###
#......#######....#..X..#.#
#.XX......X...X####..X..###
#..XXXXX..X....#..#######.#
#......X...#####.....##...#
#..###.X...#...###...#..###
##########.#..X..##..#.##.X
..X......#.#XXXXX.#..#.#.X.
..X......#.#..X.X.#..#.#.X.
..XXXXXX.###..XX..######XXX

Un callejón sin salida se define como cualquier azulejo camino que bordea n otros azulejos de carretera, al menos n-1 de las cuales se consideran extremos muertos ya por esta regla. "Bordeando" está en las cuatro direcciones cardinales, por lo que las fichas que bordean diagonalmente no cuentan.

Esta regla se aplica repetidamente, ya que los callejones sin salida recién creados pueden, por sí mismos, crear más callejones sin salida . También tenga en cuenta que cualquier mosaico de carretera que bordee solo otro mosaico de carretera se considera un callejón sin salida la primera vez que se aplica la regla.

La entrada y la salida pueden ser una sola cadena (con líneas separadas por cualquier carácter que no sea #o .) o una matriz / lista / etc. Si su idioma lo admite, también puede recibir información con cada línea como argumento de función.

Puede suponer lo siguiente acerca de la entrada:

  • Siempre habrá al menos un "bucle", es decir, un grupo de #caracteres que se pueden seguir infinitamente. (De lo contrario, cada mosaico se convertiría en un callejón sin salida).

  • Esto implica que la entrada siempre será 2 × 2 o mayor, ya que el bucle más pequeño es:

    ##
    ##
    

    (Que, dicho sea de paso, debería salir sin cambios).

  • Todos los #personajes estarán conectados. Es decir, si realizara un relleno de inundación en alguno #, todos ellos se verían afectados.

Como se trata de , ganará el código más corto en bytes.

El ejemplo anterior y la pequeña cuadrícula de 2 × 2 se pueden usar como casos de prueba (no hay muchos casos límite para cubrir en este desafío).

Respuestas:


8

CJam, 61 bytes

q_N/{{0f+zW%}4*3ew:z3few::z{e__4=_@1>2%'#e=*"#"='X@?}f%}@,*N*

Probarlo aquí .

Explicación

Outline:

    q_N/               Read input lines
        {   }@,*       Perform some operation as many times as there are bytes
                N*     Join lines

Operation:

    {0f+zW%}4*         Box the maze with zeroes
    3ew:z3few::z       Mystical 4D array neighborhood magic.
                       (Think: a 2D array of little 3x3 neighborhood arrays.)

    {                        }f%    For each neighborhood, make a new char:
     e_                                 Flatten the neighborhood
       _4=_                             Get the center tile, C
           @1>2%                        Get the surrounding tiles
                '#e=                    Count surrounding roads, n
                    *                   Repeat char C n times
                     "#"=               Is it "#"? (i.e., C = '# and n = 1)
                         'X@?           Then this becomes an 'X, else keep C.

(Martin ahorró dos bytes, ¡gracias!)


Esa es una de las respuestas cjam más largas que he visto. =)
DJMcMayhem

2
@DJMcGoathem Ummm ...
Martin Ender

¿Son '#y "#"diferentes en CJam?
ETHproductions

Sí, lo son. "#"es igual a ['#].
Lynn

5

Javascript (ES6), 110 109 bytes

r=>[...r].map(_=>r=r.replace(g=/#/g,(_,i)=>(r[i+1]+r[i-1]+r[i+l]+r[i-l]).match(g)[1]||"X"),l=~r.search`
`)&&r

¡1 byte guardado gracias a @ edc65 !

Explicación

Enfoque muy simple al problema. Busca cada uno #y, si hay menos de 2 #s alrededor, lo reemplaza con un X. Repite este proceso muchas veces hasta que se garantice que todos los callejones sin salida han sido reemplazados por Xs.

var solution =

r=>
  [...r].map(_=>                    // repeat r.length times to guarantee completeness
    r=r.replace(g=/#/g,(_,i)=>      // search for each # at index i, update r once done
      (r[i+1]+r[i-1]+r[i+l]+r[i-l]) // create a string of each character adjacent to i
      .match(g)                     // get an array of all # matches in the string
        [1]                         // if element 1 is set, return # (the match is a #)
        ||"X"                       // else if element 1 is undefined, return X
    ),
    l=~r.search`
`                                   // l = line length
  )
  &&r                               // return the updated r
<textarea id="input" rows="10" cols="40">########.....######..#..###
#......#######....#..#..#.#
#.##......#...#####..#..###
#..#####..#....#..#######.#
#......#...#####.....##...#
#..###.#...#...###...#..###
##########.#..#..##..#.##.#
..#......#.######.#..#.#.#.
..#......#.#..#.#.#..#.#.#.
..######.###..##..#########</textarea><br>
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>


1
Truco común que uso siempre para este tipo de tarea. Como usa tanto l como -l de la misma manera, puede calcular en l=~r.searchlugar de l=1+r.search. (Solo 1 byte guardado)
edc65

@ edc65 inteligente. ¡Gracias!
user81655

0

Python (3.5) 362 331 329 314 bytes

Gracias a @Alissa. ella me ayuda a ganar ~ 33 bytes

d='.'
r=range
def f(s):
 t=[list(d+i+d)for i in s.split()]
 c=len(t[0])
 u=[[d]*c]
 t=u+t+u
 l=len(t)
 g=lambda h,x:t[h][x]=='#'
 for k in r(l*c):
  for h in r(1,l):
   for x in r(1,c):
    if g(h,x) and g(h+1,x)+g(h-1,x)+g(h,x+1)+g(h,x-1)<2:
     t[h][x]='X'
 print('\n'.join([''.join(i[1:-1])for i in t][1:-1]))

Explicaciones

d='.'
r=range

Definición de la función

def f(s):

Agregue un borde de '.' a derecha e izquierda del tablero

 t=[list(d+i+d)for i in s.split()]
 c=len(t[0])
 u=[[d]*c]

Agregue un borde de '.' en la parte superior e inferior

 t=u+t+u
 l=len(t)

Función Lambda para probar '#'

 g=lambda h,x:t[h][x]=='#'

Recorre la longitud de entrada para asegurarte de que no olvidemos callejones sin salida

 for k in r(l*c):

Bucle en columnas y líneas

  for h in r(1,l):
   for x in r(1,c):

Prueba si tenemos '#' alrededor y en la posición

    if g(h,x) and g(h+1,x)+g(h-1,x)+g(h,x+1)+g(h,x-1)<2:

Reemplace '#' por 'X'

     t[h][x]='X'

Recorte el borde lleno de '.' y únete en cadena

 print('\n'.join([''.join(i[1:-1])for i in t][1:-1]))

Uso

f("########.....######..#..###\n#......#######....#..#..#.#\n#.##......#...#####..#..###\n#..#####..#....#..#######.#\n#......#...#####.....##...#\n#..###.#...#...###...#..###\n##########.#..#..##..#.##.#\n..#......#.######.#..#.#.#.\n..#......#.#..#.#.#..#.#.#.\n..######.###..##..#########")

########.....######..X..###
#......#######....#..X..#.#
#.XX......X...X####..X..###
#..XXXXX..X....#..#######.#
#......X...#####.....##...#
#..###.X...#...###...#..###
##########.#..X..##..#.##.X
..X......#.#XXXXX.#..#.#.X.
..X......#.#..X.X.#..#.#.X.
..XXXXXX.###..XX..######XXX

1) usar en split()lugar de splitlines(). 2) t=['.'*(c+2)]+['.'+i+'.'for i in s]+['.'*(c+2)]es más corto. Y se puede acortar aún más: d='.';t=[d*c]+t+[d*c];t=[d+i+d for i in t]3) no necesita toda la lista (zip (...)), useprint('\n'.join([''.join(i[1:-1])for i in t])
Alissa

@Alissa gracias por su ayuda. Uso sus consejos para el punto 1) y 3) pero para el 2) no puedo eliminar todos los corchetes, necesitamos una lista de la lista de caracteres y no una lista de cadenas porque 'str' object does not support item assignment. la lista de la lista me permite usar t [h] [x] = 'X'
Erwan

lo siento, me perdí lo de la inmutabilidad de cuerdas. También puede mover todas las constantes ( r, gy d) de su función (se ahorra algo de tabulación). Tal vez algo de jugar con split () podría ayudar: t=[d+list(i)+d for i in s.split()]luego calcule las longitudes, luego agregue líneas de puntos al final y al principio, y luego modifique sus ciclos para trabajar con estas longitudes extendidas. No estoy seguro de si acortará el código, pero podría
Alissa

@Alissa No puedo mover la g fuera de la función porque la usaré. Probaré tu otro comentario
Erwan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.