Perl 5 , -p0 105 101 96 93 90 89 octets
Utilise bau lieu de1 dans l'entrée.
Assurez-vous que la matrice sur STDIN se termine par une nouvelle ligne
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Essayez-le en ligne!
Utilise 3 niveaux de substitution!
Cette version de 87 octets est à la fois au format d'entrée et de sortie plus facile à interpréter, mais n'est pas en concurrence car elle utilise 3 caractères différents dans la sortie:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Essayez-le en ligne!
Il est facile d'enregistrer un autre octet (l'expression rationnelle s modificateur d' régulière) dans les deux versions en utilisant un caractère différent (non alphanumérique) comme terminateur de ligne (au lieu de la nouvelle ligne), mais cela rend à nouveau l'entrée assez illisible.
Comment ça fonctionne
Considérez la substitution
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
Cela trouvera deux lettres différentes et côte à côte horizontalement ou verticalement et les remplacera par c. Dans un labyrinthe dont les chemins sont entièrement constitués de la lettre, brien ne se passera car les lettres sont les mêmes, mais dès qu'une des lettres est remplacée par une autre (par exemple z), cette lettre et un voisin seront remplacés cet une application répétée est un inondation du composant connecté avec cde la semence z.
Dans ce cas, je ne veux cependant pas un remplissage complet. Je veux remplir un seul des bras voisins z, donc après la première étape, je veux qu'ils zdisparaissent. Cela fonctionne déjà avec le c$2cremplacement, mais plus tard, je veux redémarrer un remplissage d'inondation le long d'un autre bras à partir du même point et je ne sais plus lequel des cs était à l'origine z. Donc à la place j'utilise
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aest c, b | cest cet z | aest {. Donc, dans un labyrinthe avec des chemins composés bet une graine zdans la première étapeb sera remplacée par cet zsera remplacée par {ce qui n'est pas une lettre et ne correspond pas \wet ne provoquera donc pas de remplissages supplémentaires. Le ccependant gardera un nouveau remplissage d'inondation aller et un bras voisin de la graine est rempli. Par exemple à partir de
b c
b c
bbzbb becomes bb{bb
b b
b b
Je peux ensuite remplacer tous les c par des non-lettres (par exemple -) et les remplacer {à znouveau pour redémarrer le remplissage:
- -
- -
bbzbb becomes cc{bb
b b
b b
et répétez ce processus jusqu'à ce que tous les voisins de la graine aient été convertis. Si je remplace ensuite {par zet remplit:
- -
- -
--z-- stays --z--
- -
- -
Le zreste reste à la fin car il n'y a pas de voisin avec qui faire une transformation. Cela montre clairement ce qui se passe dans le fragment de code suivant:
/\n/ >
Trouvez la première nouvelle ligne. Le décalage de départ est maintenant@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
L'expression régulière discutée ci-dessus avec @{-}comme nombre de colonnes (puisque plain@- confond l'analyseur perl et ne le remplace pas correctement)
&&
Le /\n/réussit toujours et la substitution est vraie tant que nous pouvons encore remplir. Donc la partie après&& est exécutée si le remplissage d'un bras est effectué. Sinon, le côté gauche correspond à une chaîne vide
y/{c/z / > 0
Redémarrez le remplissage et retournez 1 si le remplissage précédent a fait quelque chose. Sinon, retourne la chaîne vide. Tout ce morceau de code est enveloppé à l'intérieur
s:|.: code :seg
Donc, si cela est exécuté sur une chaîne de départ $_avec un zà la position de départ, le morceau de code à l'intérieur sera exécuté plusieurs fois, la plupart du temps, ne retournant rien, mais à 1chaque fois qu'un bras voisin est rempli. Effectivement$_ détruit et remplacé par autant de 1s qu'il y a de composants connectés z. Notez que la boucle doit être exécutée jusqu'à la somme des tailles des composants + nombre de fois d'armements mais c'est OK car il y aura "nombre de caractères y compris les sauts de ligne * 2 + 1" fois.
Le labyrinthe se déconnecte s'il n'y en a pas 1(chaîne vide, sommet isolé) ou s'il y a plus de 1 bras (plus de 2 1s). Cela peut être vérifié en utilisant l'expression régulière /\B/(cela donne 0au lieu de 1sur les anciennes versions de Perl. On peut dire laquelle est fausse). Malheureusement, s'il ne correspond pas, cela donnera une chaîne vide au lieu de 0. Cependant, le a s:|.: code :segété conçu pour toujours renvoyer un nombre impair donc en faisant un &avec /\B/cela donnera 0ou 1.
Il ne reste plus qu'à parcourir l'ensemble du réseau d'entrée et à chaque position de marche avec zet compter les bras connectés. Cela se fait facilement avec:
s%b%$_="$`z$'"; code %eg
Le seul problème est que dans les positions non accessibles à pied, l'ancienne valeur est conservée. Puisque nous avons besoin de 0s, cela signifie que le tableau d'entrée d'origine doit avoir 0dans les positions non accessibles et 0correspond \wdans la substitution d'origine et déclencherait des remplissages. C'est pourquoi j'utilise à la \pLplace (uniquement des lettres de correspondance).