Martin Ender a récemment atteint 100 000 livres et a mis au point des langages assez impressionnants . Nous allons nous amuser un peu avec l'un d'eux, Hexagony (et un peu de regex pour Retina )
En résumé, vous devez écrire un programme qui entre une grille Hexagony et détermine s’il existe un chemin correspondant à une chaîne de texte.
Générateur
Hexagony génère des hexagones à partir d'une chaîne de texte en procédant comme suit:
- Calculez la taille minimum d'un hexagone (prenez la longueur de la chaîne et arrondissez au nombre hexadécimal le plus proche )
- Envelopper le texte dans un hexagone de la taille ci-dessus
- Remplir les emplacements restants avec
.
.
Par exemple, la chaîne de texte abcdefghijklm
nécessite un hexagone de côté 3 et devient donc:
a b c
d e f g
h i j k l
m . . .
. . .
Maintenant, notez qu'il y a 6 directions possibles que vous pouvez voyager dans un hexagone. Par exemple, dans l'hexagone ci-dessus, e
est adjacent à abfjid
.
Emballage
De plus, en hexagone, les hexagones enveloppent:
. . . . . a . . . . f . . a . .
a b c d e . . b . . . . g . . . b . . f
. . . . . . g . . c . . . . h . . a . c . . g .
. . . . . . . . h . . d . . . . u . . b . . d . . h . .
f g h i j k . i . . e . . j . . c . e . . i . .
. . . . . . j . . f k . . d . . . j . .
. . . . . k . . . . e . . k . .
Si vous regardez les 2ème et 4ème exemples, remarquez comment a
et si vous k
êtes au même endroit, malgré le fait que vous vous dirigiez dans des directions différentes. De ce fait, ces spots ne sont adjacents qu'à 5 autres endroits .
Pour rendre cela plus clair:
a b c d
e f g h i
j k l m n o
p q r s t u v
w x y z A B
C D E F G
H I J K
- Les bords se terminent à leur voisin opposé (
b->I
etG->j
). - Les coins supérieur / inférieur se déplacent vers le coin central opposé et vers le haut / bas (
d->K,p
etH->a,v
). - Coins centraux enveloppant les coins supérieur et inférieur (
v->a,H
)
Les chemins
Un chemin doit être une séquence d'emplacements adjacents sans revenir au même emplacement.
a b c
d e f g
h i f k l
m . . .
. . .
Dans l'hexagone ci-dessus, aefkgm
est un chemin valide. Cependant, le abfd
chemin n'est pas valide ( f
et d
ne sont pas adjacents) et abea
n'est pas valide (retourne à l' a
emplacement).
Nous pouvons utiliser ces chemins pour faire correspondre le texte (comme regex) . Un caractère alphanumérique correspond à lui-même (et uniquement à lui-même), et a .
correspond à tout caractère. Par exemple, le chemin aej..lgm
correspondrait aej..lgm
, aejAAlgm
, aeja.lgm
ou aej^%gm
.
Entrée sortie
Votre programme doit prendre deux chaînes (dans n'importe quel ordre). La première chaîne ne sera pas vide et ne comportera que des caractères alphanumériques [a-zA-Z0-9]
. Cela représentera l'hexagone sur lequel vous opérez. La deuxième chaîne sera composée de caractères imprimables.
Vous devez renvoyer une valeur de vérité si et seulement si l'hexagone contient un chemin qui correspond à la chaîne de texte donnée, sinon une valeur de falsy.
Cas de test
Vérité
"a","a"
"ab","a"
"ab","b"
"ab","ba"
"ab","aba"
"ab","&"
"ab","#7.J!"
"ab","aaaaaa"
"ab","bgjneta"
"ab","cebtmaa"
"abcdefg","dfabcg"
"AbCDeFG","GCbAeFD"
"aaaabbb","aaababb"
"abcdefghijklmnopqrs","alq"
"abcdefghijklmnopqrs","aqnmiedh"
"abcdefghijklmnopqrs","adhcgkorbefjimnqlps"
"11122233344455","12341345123245"
"abcdefgh","h%a"
"abcdefghijklm","a)(@#.*b"
"abcdefghijklm","a)(@#.*i"
"abcdefghij","ja"
"abcdefghijklmno","kgfeia"
"abcdefghijklmno","mmmmmiea"
"abcdefghijklmno","mmmmmlae"
"abcdefghijklmno","ja"
"abcdefghijklmnopqrs","eijfbadhmnokgcsrql"
Fausseté:
"a","b"
"a","%"
"a","."
"a","aa"
"a","a."
"ab","#7.J!*"
"ab","aaaaaaa"
"ab","aaaabaaa"
"ab","123456"
"abcdefg","bfgedac"
"abcdefg","gecafdb"
"abcdefg","GCbaeFD"
"aaaabbb","aaaaabb"
"abcdefghijklmnopqrs","aqrcgf"
"abcdefghijklmnopqrs","adhlcgknbeifjm"
"abcdefghijklmnopqrs","ja"
"abcdefghijklm","a)(@#.*&"
"abcdefghijklmno","a)(@bfeijk"
"abcdefghijklmno","kgfeic"
"abcdefghijklmno","mmmmmmiea"
Ceci est un code-golf , alors répondez aussi brièvement que possible dans votre langue préférée.
la source
Réponses:
Retina , 744 octets
Désolé les gars, pas d'Hexagonie cette fois ...
Le nombre d'octets suppose un codage ISO 8859-1.
Attend la chaîne cible sur la première ligne et l'hexagone sur la deuxième ligne de l'entrée. Imprime
0
ou en1
conséquence.Essayez-le en ligne! (La première ligne active une suite de tests, où chaque ligne est un scénario de test et utilise
¦
pour la séparation au lieu d'un saut de ligne.)La bonne façon de résoudre ce défi est bien sûr avec une expression régulière. ;) Et si ce n’était pas le cas, ce défi impliquait également la procédure de déploiement de l’hexagone , cette réponse ne serait en réalité constituée que d’une simple expression rationnelle longue de 600 octets.
Le jeu n’est pas encore optimal, mais je suis assez satisfait du résultat (ma première version opérationnelle, après avoir supprimé les groupes nommés et d’autres éléments nécessaires à la santé mentale, était d’environ 1000 octets). Je pense que je pourrais économiser environ 10 octets en inversant l'ordre de la chaîne et de l'hexagone, mais cela nécessiterait une réécriture complète de la regex à la fin, ce que je ne me sens pas à la hauteur. En omettant l'
G
étape, on économise également 2 octets , mais cela ralentit considérablement la solution. J'attendrai donc de faire ce changement jusqu'à ce que je sois sûr d'avoir joué au golf autant que je peux.Explication
La partie principale de cette solution utilise énormément les groupes d'équilibrage . Je vous recommande donc de les lire si vous voulez comprendre comment cela fonctionne en détail (je ne vous blâmerai pas si vous ne le faites pas ...).
La première partie de la solution (c'est-à-dire tout sauf les deux dernières lignes) est une version modifiée de ma réponse à Unfolding le code source Hexagony . Il construit l'hexagone, tout en laissant la chaîne cible intacte (et construit en fait l'hexagone avant la chaîne cible). J'ai apporté quelques modifications au code précédent pour économiser des octets:
×
remplace un espace afin d'éviter tout conflit avec des espaces potentiels dans l'entrée._
place.
, de sorte que les cellules de la grille peuvent être identifiées de manière fiable en tant que caractères de mot.Voici un exemple. Pour le cas de test suivant:
On a:
Comparez cela avec la disposition habituelle de l'hexagone:
Nous pouvons voir que les voisins sont maintenant tous les voisins habituels de 8 Moore, à l'exception des voisins du nord-ouest et du sud-est. Nous devons donc vérifier la contiguïté horizontale, verticale et sud-ouest / nord-est (bon et puis il y a les bords enveloppants). L'utilisation de cette présentation plus compacte offre également l'avantage supplémentaire de pouvoir utiliser celles-ci
××
à la fin pour déterminer la taille de l'hexagone à la volée lorsque nous en avons besoin.Une fois ce formulaire construit, nous apportons un changement supplémentaire à la chaîne entière:
Ceci remplace les chiffres par les lettres ASCII étendues
Comme ils sont remplacés à la fois dans l'hexagone et dans la chaîne cible, cela n'aura aucune incidence sur le fait que la chaîne soit identique ou non. En outre, puisque ce sont des lettres
\w
et les\b
identifient toujours comme des cellules hexagonales. L'avantage de cette substitution est que nous pouvons maintenant utiliser\D
dans la prochaine expression rationnelle pour associer n'importe quel caractère (en particulier les sauts de ligne ainsi que les caractères autres que les sauts de ligne). Nous ne pouvons pas utiliser l's
option pour accomplir cela, car nous devrons.
faire correspondre des caractères sans saut de ligne à plusieurs endroits.Maintenant le dernier bit: déterminer si un chemin correspond à notre chaîne donnée. Cela se fait avec une seule regex monstrueuse. Vous pourriez vous demander pourquoi?!?! Eh bien, c’est fondamentalement un problème de retour en arrière: vous commencez quelque part et essayez un chemin tant qu’il correspond à la chaîne, et une fois que cela ne vous retourne pas, vous essayez un voisin différent du dernier caractère qui a fonctionné. La seule choseque vous obtenez gratuitement lorsque vous travaillez avec regex est un retour en arrière. C'est littéralement la seule chose que fait le moteur regex. Donc, si nous trouvons simplement un moyen de décrire un chemin valide (ce qui est assez compliqué pour ce genre de problème, mais tout à fait possible avec des groupes d'équilibrage), le moteur des expressions rationnelles trouvera ce chemin parmi tous ceux qui sont possibles pour nous. Il serait certainement possible de mettre en œuvre la recherche manuellement avec plusieurs étapes ( et je l'ai déjà fait par le passé ), mais je doute que cela soit plus court dans ce cas particulier.
Un problème avec l'implémentation de cela avec une expression rationnelle est que nous ne pouvons pas tisser de manière arbitraire le curseur du moteur des expressions rationnelles dans la chaîne pendant le retour en arrière (ce dont nous aurions besoin, car le chemin pourrait monter ou descendre). Donc, au lieu de cela, nous gardons trace de notre propre "curseur" dans un groupe de capture et le mettons à jour à chaque étape (nous pouvons nous déplacer temporairement à la position du curseur avec un lookaround). Cela nous permet également de stocker toutes les positions passées que nous utiliserons pour vérifier que nous n'avons pas visité la position actuelle auparavant.
Alors allons-y. Voici une version légèrement plus saine de la regex, avec des groupes nommés, une indentation, un ordre moins aléatoire des voisins et quelques commentaires:
J'espère que l'idée générale en ressort clairement. À titre d'exemple du fonctionnement de l'un de ces mouvements le long du chemin, examinons le bit qui déplace le curseur vers le sud:
Rappelez-vous que les regards noirs doivent être lus de droite à gauche (ou de bas en haut), car c'est l'ordre dans lequel ils sont exécutés:
Notez qu'il n'est pas nécessaire de mettre une ancre devant le
\k<pos>
pour s'assurer que cela atteint réellement le début de la chaîne.<pos>
commence toujours par une quantité de ce×
qui ne peut être trouvé nulle part ailleurs, donc cela agit déjà comme une ancre implicite.Je ne veux pas trop encaisser ce message, je ne vais donc pas entrer dans les 11 autres cas en détail, mais en principe, ils fonctionnent tous de la même manière. Nous vérifions qu’il
<next>
peut être trouvé dans une direction spécifique (admissible) à partir de l’ancienne position du curseur à l’aide de groupes d’équilibrage, puis nous stockons la chaîne jusqu’à cette correspondance en tant que nouvelle position du curseur<pos>
.la source
Python 3,
990943770709 octetsPremière réponse, yay!
EDIT: Faire une liste de contiguïté au golf. J'utilise maintenant une formule légèrement différente
EDIT 2: Suppression des peluches inutiles, beaucoup plus joué au golf.
EDIT 3: raccourci le code pour la conversion de l’index dans la liste en coordonnées, a joué au golf encore quelques choses.
La majorité des octets est liée à la création de la liste de contiguïté (celle-ci a le plus de potentiel pour être jouée au golf). À partir de là, il s’agit simplement de forcer brutalement la solution (ce que je pourrais peut-être faire en moins d’octets).
Golfé:
Ungolfed w / explication:
Si près de la rétine! :(Ouais, bat Retina!la source
Javascript (ES6),
511500496 octetsUngolfed et commenté
Cas de test
L'extrait ci-dessous passera en revue tous les cas de vérification de la vérité et de la fausseté.
Afficher l'extrait de code
la source