Perl 5 , -p0 105 101 96 93 90 89 bytes
Usa em bvez de 1na entrada.
Verifique se a matriz no STDIN é finalizada com uma nova linha
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Experimente online!
Usa 3 níveis de substituição!
Esta versão de 87 bytes é mais fácil de interpretar nos formatos de entrada e saída, mas não está competindo, pois usa 3 caracteres diferentes na saída:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Experimente online!
É fácil salvar outro byte (o smodificador regex ) nas duas versões usando algum caractere diferente (não alfanumérico) como terminador de linha (em vez de nova linha), mas isso torna a entrada bastante ilegível novamente.
Como funciona
Considere a substituição
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
Ele encontrará duas letras diferentes e próximas umas das outras na horizontal ou na vertical e as substituirá por c. Em um labirinto cujos caminhos consistem inteiramente na letra, bnada acontecerá, pois as letras são as mesmas, mas assim que uma das letras for substituída por outra (por exemplo z), essa letra e um vizinho serão substituídos por cuma aplicação repetida. inundação do componente conectado com a cpartir da semente z.
Neste caso, no entanto, não quero um preenchimento completo. Eu quero preencher apenas um dos braços vizinhos z, então, após o primeiro passo, quero zir embora. Isso já funciona com a c$2csubstituição, mas depois pretendo reiniciar um preenchimento de inundação ao longo de outro braço, começando do mesmo ponto e não sei mais qual deles cera originalmente z. Então, ao invés, eu uso
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aé c, b | cé ce z | aé {. Assim, em um labirinto com caminhos compostos be uma semente zno primeiro passo bserá substituída ce zsubstituída pela {que não é uma letra e não corresponde \we, portanto, não causará preenchimentos adicionais. No centanto, isso manterá um novo preenchimento de inundação e um braço vizinho da semente será preenchido. Por exemplo, começando de
b c
b c
bbzbb becomes bb{bb
b b
b b
Posso, então, substituir todos os c por alguns carta não (por exemplo -) e substitua {por zoutra vez para reiniciar a inundação-fill:
- -
- -
bbzbb becomes cc{bb
b b
b b
e repita esse processo até que todos os vizinhos da semente tenham sido convertidos. Se eu substituir novamente {por ze preencher:
- -
- -
--z-- stays --z--
- -
- -
Os zrestos ficam para trás no final, porque não há vizinho com quem fazer uma transformação. Isso deixa claro o que acontece no seguinte fragmento de código:
/\n/ >
Encontre a primeira nova linha. O deslocamento inicial está agora em@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
O regex discutido acima com @{-}o número de colunas (uma vez que plain @-confunde o analisador perl e não o substitui adequadamente)
&&
O /\n/sempre é bem-sucedido e a substituição é verdadeira desde que ainda possamos inundar. Portanto, a parte seguinte &&é executada se o preenchimento de um braço for concluído. Caso contrário, o lado esquerdo é avaliado como uma sequência vazia
y/{c/z / > 0
Reinicie o preenchimento e retorne 1 se o preenchimento anterior tiver feito alguma coisa. Caso contrário, retorne a string vazia. Todo esse código está envolvido
s:|.: code :seg
Portanto, se isso for executado em uma string inicial $_com a zna posição inicial, o código dentro será executado muitas vezes retornando nada, mas 1sempre que um braço vizinho for inundado. Efetivamente $_é destruído e substituído por tantos 1s quantos componentes conectados estiverem conectados z. Observe que o loop precisa ser executado até a soma dos tamanhos dos componentes + número de vezes de armas, mas isso é bom, pois ele "número de caracteres, incluindo novas linhas * 2 + 1" vezes.
O labirinto é desconectado se não houver 1(corda vazia, um vértice isolado) ou se houver mais de 1 braço (mais de 2 1s). Isso pode ser verificado usando o regex /\B/(isso fornece, em 0vez de 1versões perl mais antigas. É discutível qual deles está errado). Infelizmente, se não corresponder, isso dará uma string vazia em vez de 0. No entanto, o s:|.: code :segfoi projetado para sempre retornar um número ímpar, fazendo um &com /\B/isso dará 0ou 1.
Tudo o que resta é caminhar por toda a matriz de entrada e, em cada posição caminhável, semear ze contar os braços conectados. Isso é feito facilmente com:
s%b%$_="$`z$'"; code %eg
O único problema é que nas posições não passíveis de passagem o valor antigo é mantido. Como precisamos de 0s lá, isso significa que a matriz de entrada original deve ter 0nas posições não passíveis de passagem e 0correspondências \wna substituição original e provocaria enchentes. É por isso que eu uso \pL(apenas as letras correspondentes).