Perl 5 , -p0 105 101 96 93 90 89 byte
Utilizza banziché 1nell'input.
Assicurarsi che la matrice su STDIN sia terminata con una nuova riga
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Provalo online!
Utilizza 3 livelli di sostituzione!
Questa versione da 87 byte è sia in formato input che output più semplice da interpretare, ma non è in competizione poiché utilizza 3 caratteri diversi nell'output:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Provalo online!
È facile salvare un altro byte (il smodificatore regex ) in entrambe le versioni utilizzando alcuni caratteri diversi (non alfanumerici) come terminatore di riga (anziché newline), ma ciò rende di nuovo l'input piuttosto illeggibile.
Come funziona
Considera la sostituzione
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
Questo troverà due lettere diverse e una accanto all'altra in senso orizzontale o verticale e sostituirle con c. In un labirinto i cui percorsi sono costituiti interamente dalla lettera bnon accadrà nulla poiché le lettere sono uguali, ma non appena una delle lettere viene sostituita da un'altra (ad es. z) Quella lettera e un vicino verranno sostituiti ce l'applicazione ripetuta è un riempimento di piena del componente collegato con cda seme z.
In questo caso, tuttavia, non voglio un riempimento completo. Voglio riempire solo una delle braccia vicine z, quindi dopo il primo passo voglio zandare. Funziona già con la c$2csostituzione, ma in seguito voglio ricominciare un riempimento inondazione lungo un altro braccio a partire dallo stesso punto e non so più quale delle cs fosse originariamente z. Quindi invece lo uso
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aè c, b | cè cez | a è {. Quindi in un labirinto con percorsi costituiti be un seme znel primo passaggio bverrà sostituito da ce zverrà sostituito da {quale non è una lettera e non corrisponde \we quindi non causerà ulteriori riempimenti. Il ctuttavia manterrà un ulteriore diluvio-fill in corso e un braccio vicino del seme si riempie. Ad esempio a partire da
b c
b c
bbzbb becomes bb{bb
b b
b b
Posso quindi sostituire tutte le lettere c con alcune non lettere (ad es. -) E sostituirle {di znuovo per riavviare il riempimento:
- -
- -
bbzbb becomes cc{bb
b b
b b
e ripetere questo processo fino a quando tutti i vicini del seme non sono stati convertiti. Se dunque io ancora una volta sostituire {da ze inondazioni riempimento:
- -
- -
--z-- stays --z--
- -
- -
Alla fine zresta dietro perché non c'è un vicino con cui fare una trasformazione. Ciò chiarisce cosa succede nel seguente frammento di codice:
/\n/ >
Trova la prima newline. L'offset iniziale è ora in@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
La regex discussa sopra con @{-}il numero di colonne (poiché plain @-confonde il parser perl e non sostituisce correttamente)
&&
Il /\n/ riesce sempre e la sostituzione è vero finché possiamo ancora alluvione-fill. Quindi la parte successiva &&viene eseguita se viene eseguito il riempimento di un braccio. In caso contrario, il lato sinistro restituisce una stringa vuota
y/{c/z / > 0
Riavviare il riempimento dell'inondazione e restituire 1 se il riempimento precedente ha fatto qualcosa. Altrimenti restituisce la stringa vuota. L'intero pezzo di codice è racchiuso all'interno
s:|.: code :seg
Quindi, se questo viene eseguito su una stringa iniziale $_con un znella posizione seed, il pezzo di codice all'interno verrà eseguito molte volte principalmente restituendo nient'altro che un1 ogni volta che un braccio vicino viene riempito. $_Viene efficacemente distrutto e sostituito da tanti 1s quanti sono i componenti collegati collegati z. Si noti che il ciclo deve essere eseguito fino alla somma delle dimensioni dei componenti + numero di tempi delle armi, ma va bene dato che sarà "numero di caratteri comprese le nuove righe * 2 + 1" volte.
Il labirinto viene disconnesso se non ci sono 1(stringa vuota, un vertice isolato) o se ci sono più di 1 braccio (più di 2 1s). Questo può essere verificato usando il regex /\B/(questo 0invece che 1nelle versioni precedenti di perl. È discutibile quale sia sbagliato). Sfortunatamente se non corrisponde questo darà una stringa vuota invece di 0. Tuttavia, è s:|.: code :segstato progettato per restituire sempre un numero dispari, quindi facendo un &con/\B/ questo darà 0o 1.
Tutto ciò che rimane è camminare sull'intero array di input e in ogni posizione di walkable seed con z e contare i bracci collegati. Questo è facile da fare con:
s%b%$_="$`z$'"; code %eg
L'unico problema è che nelle posizioni non percorribili viene mantenuto il vecchio valore. Dal momento che abbiamo bisogno di 0s lì, ciò significa che l'array di input originale deve avere 0posizioni non calpestabili e 0corrispondenze \wnella sostituzione originale e innescherebbe riempimenti. Ecco perché uso \pLinvece (solo lettere di corrispondenza).