Perl 5 , -p0
105 101 96 93 90 89 Bytes
Verwendet b
anstelle 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, c
und die wiederholte Anwendung ist a Fülle die verbundene Komponente mit c
aus 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 z
verschwunden haben. Das funktioniert bereits mit dem c$2c
Ersatz, 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 z
war. Also benutze ich stattdessen
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | a
ist c
, b | c
ist c
und z | a
ist {
. In einem Labyrinth mit Pfaden aus b
und einem Samen wird z
im ersten Schritt b
ersetzt durch c
und z
ersetzt durch, {
der kein Buchstabe ist und nicht übereinstimmt \w
und daher keine weiteren Füllungen verursacht. Das wird c
jedoch 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 z
erneutes 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 z
und 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 z
an der Startposition ausgeführt wird, wird der darin enthaltene Code mehrmals ausgeführt, wobei meistens nur ein Code zurückgegeben wird, 1
wenn ein Nachbararm überflutet wird. Effektiv$_
zerstört und durch so viele ersetzt, 1
wie 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 1
s). Dies kann mit dem regulären Ausdruck überprüft werden /\B/
(dies gibt 0
anstelle 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 0
oder 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 0
s dort benötigen , bedeutet dies, dass sich das ursprüngliche Eingabearray 0
in den nicht begehbaren Positionen befinden muss und in der ursprünglichen Substitution 0
übereinstimmt \w
und Überschwemmungen auslösen würde. Deshalb verwende ich \pL
stattdessen (nur Matchbuchstaben).