Perl 5 , -p0 105 101 96 93 90 89 bytes
Utiliza en blugar de 1en la entrada.
Asegúrese de que la matriz en STDIN termine con una nueva línea
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Pruébalo en línea!
Utiliza 3 niveles de sustitución!
Esta versión de 87 bytes es más fácil de interpretar en formato de entrada y salida, pero no compite ya que utiliza 3 caracteres diferentes en la salida:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Pruébalo en línea!
Es fácil guardar otro byte (el smodificador regex ) en ambas versiones usando algún carácter diferente (no alfanumérico) como terminador de fila (en lugar de nueva línea), pero eso hace que la entrada sea completamente ilegible nuevamente.
Cómo funciona
Considera la sustitución
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
Esto encontrará dos letras que son diferentes y una al lado de la otra horizontal y verticalmente y las reemplazará por c. En un laberinto cuyas rutas consisten completamente en la letra, bno pasará nada, ya que las letras son las mismas, pero tan pronto como una de las letras sea reemplazada por otra (por ejemplo z), esa letra y un vecino serán reemplazados por cuna aplicación repetida. relleno de inundación del componente conectado con la csemilla z.
En este caso, sin embargo, no quiero un relleno de inundación completo. Quiero llenar solo uno de los brazos vecinos z, así que después del primer paso quiero que se zvaya. Eso ya funciona con el c$2creemplazo, pero luego quiero reiniciar un relleno de inundación a lo largo de otro brazo a partir del mismo punto y ya no sé cuál de los cs era originalmente z. Entonces en su lugar uso
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aes c, b | ces cy z | aes {. Por lo tanto, en un laberinto con caminos formados by una semilla zen el primer paso bserá reemplazada por cy zserá reemplazada por una {que no es una letra y no coincide \wy, por lo tanto, no causará más rellenos. Sin cembargo, esto mantendrá un nuevo llenado de inundación y un brazo vecino de la semilla se llenará. Ej. A partir de
b c
b c
bbzbb becomes bb{bb
b b
b b
Entonces puedo reemplazar todo c por alguna letra que no sea (por ejemplo -) y reemplazar {de znuevo para reiniciar el relleno de inundación:
- -
- -
bbzbb becomes cc{bb
b b
b b
y repita este proceso hasta que todos los vecinos de la semilla se hayan convertido. Si luego, una vez más, reemplazo {por zy relleno de inundación:
- -
- -
--z-- stays --z--
- -
- -
Los zrestos quedan al final porque no hay ningún vecino con el que hacer una transformación. Eso deja en claro lo que sucede en el siguiente fragmento de código:
/\n/ >
Encuentra la primera línea nueva. El desplazamiento inicial ahora está en@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
La expresión regular discutida anteriormente con el @{-}número de columnas (ya que simple @-confunde el analizador perl y no sustituye adecuadamente)
&&
El /\n/siempre tiene éxito y la sustitución es verdadera siempre que podamos llenarnos de inundaciones. Por lo tanto, la parte posterior &&se ejecuta si se completa el relleno de un brazo. Si no, el lado izquierdo se evalúa como una cadena vacía
y/{c/z / > 0
Reinicie el relleno de inundación y devuelva 1 si el relleno de inundación anterior hizo algo. De lo contrario, devuelva la cadena vacía. Todo este código está envuelto dentro
s:|.: code :seg
Por lo tanto, si esto se ejecuta en una cadena de inicio $_con una zposición inicial, el código del interior se ejecutará muchas veces, en su mayoría, devolverá nada más que 1cada vez que un brazo vecino se llene de inundaciones. Efectivamente $_se destruye y se reemplaza por tantos 1s como haya componentes conectados conectados z. Tenga en cuenta que el bucle debe ejecutarse hasta la suma de los tamaños de los componentes + el número de veces de brazos, pero eso está bien ya que "número de caracteres, incluidas las nuevas líneas * 2 + 1" veces.
El laberinto se desconecta si no hay 1's (cadena vacía, un vértice aislado) o si hay más de 1 brazos (más de 2 1s). Esto se puede verificar usando la expresión regular /\B/(esto da en 0lugar de 1versiones anteriores de perl. Es discutible cuál está mal). Desafortunadamente, si no coincide, esto dará una cadena vacía en lugar de 0. Sin embargo, el s:|.: code :segfue diseñado para devolver siempre un número impar, por lo que al hacer un &con /\B/esto dará 0o 1.
Todo lo que queda es recorrer toda la matriz de entrada y en cada posición transitable se siembra zy cuenta los brazos conectados. Eso se hace fácilmente con:
s%b%$_="$`z$'"; code %eg
El único problema es que en las posiciones no transitables se retiene el valor anterior. Como necesitamos 0s allí, eso significa que la matriz de entrada original debe tener 0en las posiciones y 0coincidencias no transitables \wen la sustitución original y provocaría rellenos de inundación. Es por eso que uso \pLen su lugar (solo letras coincidentes).