Perl 5 , -p0 105 101 96 93 90 89 Bytes
Verwendet banstelle von1 in der Eingabe.
Stellen Sie sicher, dass die Matrix auf STDIN mit einem Zeilenumbruch abgeschlossen ist
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Probieren Sie es online!
Verwendet 3 Substitutionsstufen!
Diese 87-Byte-Version ist sowohl im Eingabe- als auch im Ausgabeformat einfacher zu interpretieren, konkurriert jedoch nicht, da sie drei verschiedene Zeichen in der Ausgabe verwendet:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Probieren Sie es online!
Es ist einfach, ein weiteres Byte (den regulären Ausdruck) zu speichern s Modifikator) in beiden Versionen indem ein anderes (nicht alphanumerisches) Zeichen als Zeilenabschlusszeichen (anstelle von Zeilenvorschub) verwendet wird. Dadurch ist die Eingabe jedoch wieder ziemlich unlesbar.
Wie es funktioniert
Betrachten Sie die Substitution
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
Dies findet zwei Buchstaben, die horizontal oder vertikal nebeneinander liegen und ersetzt sie durch c. In einem Labyrinth, dessen Wege vollständig aus dem Buchstaben bestehen b, passiert nichts, da die Buchstaben gleich sind, aber sobald einer der Buchstaben durch einen anderen ersetzt wird (z. B. z), werden dieser Buchstabe und ein Nachbar durch einen anderen ersetzt, cund die wiederholte Anwendung ist a Fülle die verbundene Komponente mit caus Samenz .
In diesem Fall möchte ich jedoch keine vollständige Überflutung. Ich möchte nur einen der benachbarten Arme ausfüllen z, also möchte ich nach dem ersten Schritt den zverschwunden haben. Das funktioniert bereits mit dem c$2cErsatz, aber ich möchte später eine Überflutung entlang eines anderen Arms ab dem gleichen Punkt neu starten, und ich weiß nicht, welcher der beidenc s ursprünglich zwar. Also benutze ich stattdessen
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aist c, b | cist cund z | aist {. In einem Labyrinth mit Pfaden aus bund einem Samen wird zim ersten Schritt bersetzt durch cund zersetzt durch, {der kein Buchstabe ist und nicht übereinstimmt \wund daher keine weiteren Füllungen verursacht. Das wird cjedoch eine weitere Überflutung am Laufen halten und ein Nachbararm des Samens wird gefüllt. ZB ab
b c
b c
bbzbb becomes bb{bb
b b
b b
Ich kann dann alles c durch einen Nicht-Buchstaben (zB -) ersetzen und {durch zerneutes ersetzen , um die Überflutung neu zu starten:
- -
- -
bbzbb becomes cc{bb
b b
b b
und wiederholen Sie diesen Vorgang, bis alle Nachbarn des Samens konvertiert wurden. Wenn ich dann nochmal {durch ersetze zund fülle:
- -
- -
--z-- stays --z--
- -
- -
Das z bleibt am Ende zurück, weil es keinen Nachbarn gibt, mit dem man eine Transformation machen kann. Das macht deutlich, was im folgenden Codefragment passiert:
/\n/ >
Finde den ersten Zeilenumbruch. Der Startoffset ist jetzt in@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
Der oben diskutierte reguläre Ausdruck mit @{-}der Anzahl der Spalten (da plain @-den Perl-Parser verwirrt und nicht richtig ersetzt)
&&
Das /\n/gelingt immer und die Substitution ist so lange wahr, wie wir uns noch überfluten können. Der Teil danach &&wird also ausgeführt, wenn die Überflutung eines Arms erfolgt ist. Wenn nicht, ergibt die linke Seite eine leere Zeichenfolge
y/{c/z / > 0
Starten Sie die Überflutung neu und geben Sie 1 zurück, wenn die vorherige Überflutung etwas bewirkt hat. Anderenfalls geben Sie die leere Zeichenfolge zurück. Dieses ganze Stück Code ist darin eingewickelt
s:|.: code :seg
Wenn dies also an einer Startzeichenfolge $_mit einem zan der Startposition ausgeführt wird, wird der darin enthaltene Code mehrmals ausgeführt, wobei meistens nur ein Code zurückgegeben wird, 1wenn ein Nachbararm überflutet wird. Effektiv$_ zerstört und durch so viele ersetzt, 1wie angeschlossene Komponenten vorhanden sindz . Beachten Sie, dass die Schleife bis zur Summe der Komponentengrößen und der Anzahl der Arme ausgeführt werden muss. Dies ist jedoch in Ordnung, da die Anzahl der Zeichen einschließlich der Zeilenumbrüche 2 + 1 beträgt.
Das Labyrinth wird getrennt, wenn keine vorhanden sind 1(leere Zeichenfolge, ein isolierter Scheitelpunkt) oder wenn mehr als 1 Arme vorhanden sind (mehr als 2 1s). Dies kann mit dem regulären Ausdruck überprüft werden /\B/(dies gibt 0anstelle von 1älteren Perl-Versionen. Es ist fraglich, welcher falsch ist). Wenn es nicht passt, wird leider eine leere Zeichenfolge anstelle von angezeigt 0. Dies:|.: code :seg wurde entwickelt , um immer so eine ungerade Zahl zurückgeben , indem Sie ein &mit /\B/diesem geben 0oder 1.
Alles, was übrig bleibt, ist das Gehen des gesamten Eingabearrays und bei jeder begehbaren Position den Samen mit z und Zählen der verbundenen Arme. Das geht ganz einfach mit:
s%b%$_="$`z$'"; code %eg
Das einzige Problem ist, dass in den nicht begehbaren Positionen der alte Wert beibehalten wird. Da wir 0s dort benötigen , bedeutet dies, dass sich das ursprüngliche Eingabearray 0in den nicht begehbaren Positionen befinden muss und in der ursprünglichen Substitution 0übereinstimmt \wund Überschwemmungen auslösen würde. Deshalb verwende ich \pLstattdessen (nur Matchbuchstaben).