Un labyrinthe sur une grille N par N de cellules carrées est défini en spécifiant si chaque bord est un mur ou non. Tous les bords extérieurs sont des murs. Une cellule est définie en tant que début et une cellule en tant que sortie et la sortie est accessible depuis le début. Le début et la sortie ne sont jamais la même cellule.
Notez que ni le début ni la sortie ne doivent se trouver sur la bordure extérieure du labyrinthe. Il s’agit donc d’un labyrinthe valide:
Une chaîne de caractères 'N', 'E', 'S' et 'W' indique une tentative de déplacement vers le nord, l'est, le sud et l'ouest. Un mouvement bloqué par un mur est ignoré sans mouvement. Une chaîne quitte un labyrinthe si l'application de cette chaîne depuis le début a pour résultat que la sortie est atteinte (que la chaîne continue ou non après avoir atteint la sortie).
Inspiré par cette question énigmatique.SE pour laquelle xnor a fourni une méthode éprouvée de résolution avec une très longue chaîne, écrivez du code capable de trouver une chaîne unique sortant d'un labyrinthe 3 par 3.
Si vous excluez les labyrinthes non valides (démarrage et sortie de la même cellule ou sortie inaccessible au début), il existe 138 172 labyrinthes valides et la chaîne doit quitter chacun d'eux.
Validité
La chaîne doit satisfaire les critères suivants:
- Il est composé uniquement des caractères "N", "E", "S" et "W".
- Il quitte tous les labyrinthes auxquels il est appliqué, s'il a été démarré au début.
Étant donné que l'ensemble de tous les labyrinthes possibles inclut chaque labyrinthe possible avec chaque point de départ valide, cela signifie automatiquement que la chaîne quittera tout labyrinthe de tout point de départ valide. C'est-à-dire à partir de n'importe quel point de départ à partir duquel la sortie est accessible.
Gagnant
Le gagnant est la réponse qui fournit la chaîne valide la plus courte et inclut le code utilisé pour la produire. Si plus d'une réponse fournit une chaîne de cette longueur la plus courte, le premier à poster cette longueur de chaîne l'emporte.
Exemple
Voici un exemple de chaîne de 500 caractères, pour vous donner quelque chose à battre:
SEENSSNESSWNNSNNNNWWNWENENNWEENSESSNENSESWENWWWWWENWNWWSESNSWENNWNWENWSSSNNNNNNESWNEWWWWWNNNSWESSEEWNENWENEENNEEESEENSSEENNWWWNWSWNSSENNNWESSESNWESWEENNWSNWWEEWWESNWEEEWWSSSESEEWWNSSEEEEESSENWWNNSWNENSESSNEESENEWSSNWNSEWEEEWEESWSNNNEWNNWNWSSWEESSSSNESESNENNWEESNWEWSWNSNWNNWENSNSWEWSWWNNWNSENESSNENEWNSSWNNEWSESWENEEENSWWSNNNNSSNENEWSNEEWNWENEEWEESEWEEWSSESSSWNWNNSWNWENWNENWNSWESNWSNSSENENNNWSSENSSSWWNENWWWEWSEWSNSSWNNSEWEWENSWENWSENEENSWEWSEWWSESSWWWNWSSEWSNWSNNWESNSNENNSNEWSNNESNNENWNWNNNEWWEWEE
Merci à orlp pour ce don.
Classement
Les scores égaux sont listés dans l'ordre d'affichage de ce score. Ce n'est pas nécessairement l'ordre dans lequel les réponses ont été postées car le score d'une réponse donnée peut être mis à jour au fil du temps.
Juge
Voici un validateur Python 3 qui prend une chaîne de NESW comme argument de ligne de commande ou via STDIN.
Pour une chaîne non valide, cela vous donnera un exemple visuel d'un labyrinthe pour lequel il échoue.
la source
Réponses:
C ++,
979593918683828179 caractèresMa stratégie est assez simple: un algorithme d'évolution capable de croître, de réduire, d'échanger des éléments et de muter des séquences valides. Ma logique d'évolution est maintenant presque identique à celle de @ Sp3000, car c'était une amélioration par rapport à la mienne.
Cependant, mon implémentation de la logique du labyrinthe est plutôt astucieuse. Cela me permet de vérifier si les chaînes sont valides à une vitesse fulgurante. Essayez de comprendre en regardant le commentaire
do_move
et leMaze
constructeur.la source
do_move
est maintenant incroyablement rapide.Python 3 + PyPy,
82 à80 caractèresJ’ai hésité à poster cette réponse car j’ai en gros adopté l’approche d’orlp et j’ai fait mes propres commentaires. Cette chaîne a été trouvée en commençant par une solution de longueur pseudo-aléatoire 500 - un grand nombre de graines ont été essayées avant que je puisse battre le record actuel.
La seule nouvelle optimisation majeure est que je ne regarde qu'un tiers des labyrinthes. Deux catégories de labyrinthes sont exclues de la recherche:
<= 7
places sont accessiblesL'idée est que toute corde qui résout le reste des labyrinthes devrait également résoudre ce qui précède automatiquement. Je suis convaincu que cela est vrai pour le second type, mais ce n'est certainement pas le cas pour le premier. Le résultat contiendra donc des faux positifs qui doivent être vérifiés séparément. Ces faux positifs manquent généralement environ 20 labyrinthes, alors j'ai pensé que ce serait un bon compromis entre vitesse et précision, et que cela donnerait également aux cordes un peu plus de temps pour respirer.
Au départ, j'ai passé en revue une longue liste d'heuristiques de recherche, mais, horriblement, aucune d'entre elles n'a proposé quelque chose de meilleur que 140 ou plus.
la source
0
len
long du chemin et supposez que cette chaîneS
vous mène de0
àn
. Ensuite,S
vous obtenez également de n'importe quelle cellule intermédiairec
àn
. Supposons le contraire. Soita(i)
la position après lesi
étapes commençant à0
etb(i)
commençant àc
. Ensuitea(0) = 0 < b(0)
, chaque étape changea
etb
d’au plus 1, eta(|S|) = n > b(|S|)
. Prenez le plus petitt
tel quea(t) >= b(t)
. Clairementa(t) != b(t)
ou ils seraient synchronisés, ils doivent donc changer de place à past
en se déplaçant dans la même direction.C ++ et la bibliothèque de Lingeling
En utilisant une approche SAT , je pourrais résoudre complètement le problème similaire des labyrinthes 4x4 avec des cellules bloquées au lieu de parois minces et de positions de départ et de sortie fixes aux angles opposés. J'espérais donc pouvoir utiliser les mêmes idées pour résoudre ce problème. Cependant, même si pour l'autre problème, je n'ai utilisé que 2423 labyrinthes (entre-temps, 2083 suffisent) et qu'il a une solution de longueur 29, le codage SAT a utilisé des millions de variables et sa résolution a pris des jours.
J'ai donc décidé de modifier l'approche de deux manières importantes:
J'ai également fait quelques optimisations pour utiliser moins de variables et de clauses unitaires.
Le programme est basé sur @ orlp. Un choix important a été le choix des labyrinthes:
is_solution
vérifie si toutes les positions accessibles sont atteintes.De cette façon, je reçois un total de 10772 labyrinthes avec des positions de départ.
Voici le programme:
Tout d’abord,
configure.sh
puismake
lelingeling
résolveur, compilez le programme avec quelque chose commeg++ -std=c++11 -O3 -I ... -o m3sat m3sat.cc -L ... -llgl
, où...
est le chemin oùlglib.h
resp.liblgl.a
sont, de sorte que les deux pourraient par exemple être../lingeling-<version>
. Ou tout simplement les mettre dans le même répertoire et se passer des options-I
et-L
.Le programme prend un argument de ligne de commande obligatoire, une chaîne constituée de
N
,E
,S
,W
(pour les directions fixes) ou*
. Vous pouvez donc rechercher une solution générale de taille 78 en donnant une chaîne de 78*
s (entre guillemets), ou rechercher une solution en commençant parNEWS
en utilisantNEWS
suivi de autant de*
s que vous le souhaitez pour des étapes supplémentaires. Comme premier test, prenez votre solution préférée et remplacez certaines des lettres par*
. Cela trouve une solution rapide pour une valeur étonnamment élevée de "certains".Le programme indiquera le labyrinthe ajouté, décrit par la structure du mur et la position de départ, ainsi que le nombre de positions et de murs accessibles. Les labyrinthes sont triés selon ces critères et le premier non résolu est ajouté. Par conséquent, la plupart des labyrinthes ajoutés ont
(9/4)
, mais parfois d'autres apparaissent également.J'ai pris la solution connue de longueur 79 et, pour chaque groupe de 26 lettres adjacentes, j'ai essayé de les remplacer par 25 lettres. J'ai également essayé de supprimer 13 lettres du début et de la fin et de les remplacer par 13 au début et 12 à la fin, et inversement. Malheureusement, tout est sorti insatisfiable. Alors, pouvons-nous prendre cela comme indicateur que la longueur 79 est optimale? Non, j'ai également essayé d'améliorer la solution de longueur 80 à longueur 79, et cela n'a pas non plus abouti.
Enfin, j'ai essayé de combiner le début d'une solution avec la fin de l'autre et également avec une solution transformée par l'une des symétries. Maintenant que je manque d’idées intéressantes, j’ai décidé de vous montrer ce que j’avais, même si cela n’a pas débouché sur de nouvelles solutions.
la source