introduction
Si vous n'êtes pas familier avec Hexagony , c'est un langage ésotérique créé par Martin Büttner. Le fait est que cette langue accepte plusieurs formes pour le programme. Les programmes suivants sont tous équivalents:
abcdefg
et
a b
c d e
f g
Donc, fondamentalement, le code a été condensé dans un hexagone régulier. Mais notez que l'ajout d'une nouvelle commande au code, qui abcdefgh
se traduirait par le programme suivant:
a b c
d e f g
h . . . .
. . . .
. . .
Comme vous pouvez le constater, la première étape consiste à transformer le code en hexagone, puis l'hexagone est rempli de no-ops ( .
) jusqu'au nombre hexagonal centré suivant .
Votre tâche est simple: lorsqu’une chaîne (le code source) est donnée, vous devez générer le code source hexagonal complet.
Les règles
- Vous pouvez fournir un programme ou une fonction.
- Les espaces blancs sont autorisés, mais uniquement lorsque l'hexagone ne se déforme pas
- Les espaces de fin sont autorisés.
- Notez que les espaces dans le programme sont ignorés . Donc
a b c
est égal àabc
- Seuls les caractères ASCII imprimables (
32 - 126
) sont utilisés, de sorte que seul leSpace
caractère normal est ignoré. - Supposons que la longueur de la chaîne est supérieure à 0.
- C'est du code-golf , donc la soumission avec le moins d'octets gagne!
Cas de test
Input: ?({{&2'2':{):!/)'*/
Output:
? ( {
{ & 2 '
2 ' : { )
: ! / )
' * /
Input: H;e;l;d;*;r;o;Wl;;o;*433;@.>;23<\4;*/
Output:
H ; e ;
l ; d ; *
; r ; o ; W
l ; ; o ; * 4
3 3 ; @ . >
; 2 3 < \
4 ; * /
Input: .?'.) .@@/'/ .!.> +=(<.!)} ( $>( <%
Output:
. ? ' .
) . @ @ /
' / . ! . >
+ = ( < . ! )
} ( $ > ( <
% . . . .
. . . .
abc`defg
, en fait, il deviendrait pastebin.com/ZrdJmHiR`
caractères)."Réponses:
Pyth,
575450494846Suite de tests
Imprime un espace de début sur chaque ligne.
Cette version nécessite une preuve que 10 ^ n> = 3n (n - 1) + 1 pour tout n> = 1 . Merci à ANerdI et ErickWong d’ avoir fourni des preuves.
Suite à ces inégalités: 10 ^ n> (1 + 3) ^ n = 1 + 3n + 9n (n - 1) + ...> 3n (n - 1) + 1 on peut facilement voir que cela est correct pour n> = 2 . Examiner le cas n = 1 est plutôt trivial, donnant 10> 1 .
Alternativement, prendre deux fois les dérivées de ces équations montre que 10 ^ n a une dérivée seconde plus grande pour tout n> = 1 , qui peut ensuite être cascadée jusqu'aux dérivées premières, et finalement aux équations originales.
Explication
la source
Hexagonie , 271 octets
Je vous présente les premiers 3% d'un auto-interprète Hexagony ...
Essayez-le en ligne! Vous pouvez également l'exécuter sur lui-même, mais cela prendra environ 5 à 10 secondes.
En principe, cela pourrait correspondre à la longueur de côté 9 (pour un score de 217 ou moins), car elle utilise seulement 201 commandes, et la version non-golfée que j'ai écrite en premier (sur la longueur de côté 30) ne nécessitait que 178 commandes. Cependant, je suis à peu près sûr que cela prendrait une éternité pour que tout rentre dans l'ordre, donc je ne suis pas sûr de vouloir réellement le tenter.
Il devrait également être possible de jouer au golf un peu en taille 10 en évitant d’utiliser la dernière ou les deux dernières lignes, de sorte que les no-ops suivants puissent être omis, mais que cela nécessiterait une réécriture substantielle, comme l’un des premiers chemins. joint utilise le coin inférieur gauche.
Explication
Commençons par déplier le code et annoter les chemins de flux de contrôle:
C’est toujours assez compliqué, donc voici le même schéma pour le code "non-golfé" que j’ai écrit en premier (en fait, c’est le côté de longueur 20 et à l’origine j’ai écrit le code sur le côté de 30, mais c’était tellement n’améliore pas la lisibilité du tout, alors je l’ai compactée un peu pour rendre la taille un peu plus raisonnable):
Cliquez pour agrandir.
Les couleurs sont exactement les mêmes, à l'exception de quelques détails très mineurs, les commandes sans contrôle sont également identiques. Je vais donc expliquer comment cela fonctionne sur la version sans-golf, et si vous voulez vraiment savoir comment fonctionne le golfé, vous pouvez vérifier quelles sont les parties correspondantes dans le plus grand hexagone. (Le seul problème est que le code de golf commence par un miroir de sorte que le code commence dans le coin droit en partant de la gauche.)
L'algorithme de base est presque identique à ma réponse CJam . Il y a deux différences:
.
si c'est le cas.Cela signifie que l’idée de base se résume à:
N
(et le nombre hexagonal centré correspondanthex(N)
) pouvant contenir l’entrée entière.2N-1
.2N-1
). Imprimez le retrait, imprimez les cellules (en utilisant.
si l’entrée est déjà épuisée), imprimez un saut de ligne.Notez qu'il n'y a que des no-ops et que le code actuel commence dans le coin gauche (le
$
, qui saute par-dessus le>
, donc nous commençons vraiment,
par le chemin dans le gris foncé).Voici la grille de mémoire initiale:
Ainsi, le pointeur de mémoire commence sur l’ entrée étiquetée par le bord , en direction du nord.
,
lit un octet de STDIN ou un-1
si nous avons atteint EOF dans ce bord. Par conséquent, la<
droite après est une condition pour savoir si nous avons lu toutes les entrées. Restons dans la boucle d'entrée pour l'instant. Le prochain code que nous exécutons estCeci écrit un 32 dans l' espace marqué par le bord , puis le soustrait de la valeur d'entrée dans le bord nommé diff . Notez que cela ne peut jamais être négatif car nous avons la garantie que l'entrée ne contient que de l'ASCII imprimable. Ce sera zéro quand l'entrée était un espace. (Comme Timwi le fait remarquer, cela fonctionnerait toujours si l'entrée pouvait contenir des sauts de ligne ou des tabulations, mais cela effacerait également tous les autres caractères non imprimables avec des codes de caractère inférieurs à 32.) Dans ce cas, le
<
pointeur d'instruction (IP) dévie et le chemin gris clair est pris. Ce chemin réinitialise simplement la position du député avec{=
puis lit le caractère suivant - ainsi, les espaces sont ignorés. Sinon, si le personnage n'était pas un espace, nous exécutonsCette première se déplace autour de l'hexagone à travers le bord de la longueur jusqu'à son opposé au bord du diff , avec
=}}}
. Ensuite , il copie la valeur de face de la longueur bord dans la longueur bord, et incrémente avec)&'+'+)
. Nous verrons dans une seconde pourquoi cela a du sens. Enfin, nous déplaçons le nouveau bord avec=}
:(Les valeurs de bord particulières proviennent du dernier cas de test donné dans le défi.) À ce stade, la boucle se répète, mais avec tout ce qui a été déplacé d'un hexagone au nord-est. Donc après avoir lu un autre personnage, nous obtenons ceci:
Vous pouvez maintenant voir que nous écrivons progressivement l'entrée (espaces moins) le long de la diagonale nord-est, avec les caractères sur chaque bord et la longueur jusqu'à ce caractère étant stockée parallèlement à la longueur étiquetée .
Lorsque nous aurons terminé avec la boucle d'entrée, la mémoire ressemblera à ceci (où j'ai déjà étiqueté quelques nouveaux bords pour la partie suivante):
Le
%
dernier caractère lu est le dernier,29
le nombre de caractères non-espace lus. Maintenant, nous voulons trouver la longueur de côté de l'hexagone. Premièrement, il existe un code d’initialisation linéaire dans le chemin vert foncé / gris:Ici,
=&
copie la longueur (29 dans notre exemple) dans le bord étiqueté longueur . Puis''3
passe à l’arête étiquetée 3 et définit sa valeur sur3
(ce dont nous avons simplement besoin comme constante dans le calcul). Enfin{
se déplace vers le bord marqué N (N-1) .Maintenant nous entrons dans la boucle bleue. Cette boucle incrémente
N
(stockée dans la cellule N ) calcule ensuite son nombre hexagonal centré et le soustrait de la longueur entrée. Le code linéaire utilisé est:Ici,
{)
se déplace et incrémente N .')&(
se déplace vers le bord libellé N-1 ,N
y copie et le décrémente.{=*
calcule leur produit en N (N-1) .'*)
multiplie cela par la constante3
et incrémente le résultat dans l'arête nommée hex (N) . Comme prévu, il s'agit du nième nombre hexagonal centré. Enfin'-
calcule la différence entre cela et la longueur d’entrée. Si le résultat est positif, la longueur du côté n'est pas encore assez grande et la boucle se répète (où}}
ramène le MP vers le bord marqué N (N-1) ).Une fois que le côté est assez grand, la différence sera nulle ou négative et nous obtenons ceci:
Tout d'abord, il y a maintenant le très long chemin vert linéaire qui fait l'initialisation nécessaire pour la boucle de sortie:
Les
{=&
départs en copiant le résultat dans la diff bord dans la longueur bord, parce que nous avons besoin de quelque chose là non positif plus tard.}}}32
écrit un 32 dans le bord étiqueté espace .'"2
écrit une constante 2 dans le bord non étiqueté au-dessus de diff .'=&
copieN-1
dans le deuxième bord avec la même étiquette.'*)
multiplie-le par 2 et incrémente-le de manière à obtenir la valeur correcte dans le bord appelé 2N-1 en haut. C'est le diamètre de l'hexagone.{=&')&
copie le diamètre dans l'autre bord étiqueté 2N-1 . Enfin,}}
retourne au bord marqué 2N-1 en haut.Ré-étiquetons les bords:
Le bord sur lequel nous sommes actuellement (qui a toujours le diamètre de l'hexagone) sera utilisé pour parcourir les lignes de la sortie. Le bord intitulé indent calcule le nombre d'espaces nécessaires sur la ligne en cours. Les cellules étiquetées sur le bord seront utilisées pour parcourir le nombre de cellules dans la ligne en cours.
Nous sommes maintenant sur le chemin rose qui calcule le retrait .
('-
décrémente l' itérateur de lignes et le soustrait de N-1 (dans le bord indenté ). La courte branche bleu / gris du code calcule simplement le module du résultat (~
annule la valeur si elle est négative ou nulle et rien ne se produit si elle est positive). Le reste du chemin rose est celui"-~{
qui soustrait le retrait du diamètre dans le bord des cellules , puis revient au bord du retrait .Le chemin jaune sale imprime maintenant l'indentation. Le contenu de la boucle est vraiment juste
Où
'"
se déplace vers le bord de l' espace , l';
imprime,{}
revient en retrait et le(
décrémente.Lorsque nous en avons terminé, le (deuxième) chemin gris foncé recherche le caractère suivant à imprimer. Le
=}
déplace en position (ce qui signifie, sur le bord des cellules , en direction du sud). Nous avons ensuite une boucle très étroite{}
qui descend simplement de deux côtés dans la direction sud-ouest, jusqu'à atteindre la fin de la chaîne stockée:Notez que j'ai rebaptisé un bord là-bas EOF? . Une fois que nous avons traité ce caractère, nous allons rendre ce bord négatif, afin que la
{}
boucle se termine ici au lieu de la prochaine itération:Dans le code, nous sommes à la fin du chemin gris foncé, où nous
'
revenons d'un pas sur le caractère saisi. Si la situation est l’un des deux derniers diagrammes (c’est-à-dire qu’il reste encore un caractère de l’entrée que nous n’avons pas encore imprimée), nous prenons le chemin vert (le dernier, pour les personnes qui ne sont pas douées avec le vert et le vert). bleu). Celui-là est assez simple:;
imprime le personnage lui-même.'
se déplace vers le bord d' espace correspondant qui contient toujours un 32 parmi les précédents et;
imprime cet espace. Alors{~
fait notre EOF? négatif pour la prochaine itération,'
recule d'un pas afin que nous puissions revenir à l'extrémité nord-ouest de la chaîne avec une autre}{
boucle serrée . Qui se termine sur la longueurcellule (la cellule positive au-dessous de l’ hex (N) . Enfin,}
retourne au bord de la cellule .Si nous avons déjà épuisé les entrées, alors la boucle qui recherche EOF? se terminera réellement ici:
Dans ce cas ,
'
se déplace sur la longueur cellule, et nous prenons le chemin bleu clair ( en haut) au lieu, qui imprime un no-op. Le code dans cette branche est linéaire:Le
{*46;
écrit un 46 dans le bord étiqueté no-op et l’imprime (c’est-à-dire un point). Puis{{;
passe au bord de l’ espace et l’imprime. Le{{=
retourne au bord des cellules pour la prochaine itération.À ce stade, les chemins se rejoignent et
(
décrémentent le bord des cellules . Si l'itérateur n'est pas encore à zéro, nous prendrons le chemin gris clair, qui inverse simplement la direction du député,=
puis cherche le caractère suivant à imprimer.Sinon, nous avons atteint la fin de la ligne en cours et l’IP prend le chemin violet. Voici à quoi ressemble la grille mémoire:
Le chemin violet contient ceci:
Le
=
renverse la direction du député à nouveau.M8
définit sa valeur sur778
(car le code de caractèreM
is77
et digits s'ajoutent à la valeur actuelle). C’est ce qui se produit10 (mod 256)
. Ainsi, lorsque nous l’imprimons avec;
, nous obtenons un saut de ligne. Rend ensuite~
le bord négatif,'"
revient au bord des lignes et=
inverse le MP une fois de plus.Maintenant, si le bord des lignes est zéro, nous avons terminé. L’IP prendra le chemin rouge (très court), qui
@
termine le programme. Sinon, nous continuons sur le chemin violet qui reboucle dans le rose pour imprimer une autre ligne.Diagrammes de flux de contrôle créés avec HexagonyColorer de Timwi . Diagrammes de mémoire créés avec le débogueur visuel dans son IDE Esoteric .
la source
CJam,
56525048 octetsMa première pensée a été: "hé, j'ai déjà du code pour ça!" Mais ensuite, je ne pouvais pas être dérangé pour rassembler les éléments nécessaires du code Ruby, notamment parce qu’ils ne semblaient pas très aptes à jouer au golf. J'ai donc essayé quelque chose d'autre dans CJam à la place ...
Testez-le ici.
Explication
Un peu de maths sur les nombres hexagonaux centrés en premier. Si l'hexagone régulier a une longueur de côté
N
, il contiendra des3N(N-1)+1
cellules, qui doivent être égales à la longueur du code sourcek
. Nous pouvons résoudre celaN
parce que c'est une simple équation du second degré:Nous pouvons ignorer la racine négative, car cela donne un N. négatif. Pour que cela ait une solution, nous avons besoin que la racine carrée soit un demi-entier. Ou en d'autres termes,
√(1 + 4(k-1)/3) = √((4k-1)/3)
doit être un entier (heureusement, cet entier est le diamètreD = 2N-1
de l'hexagone, ce dont nous aurons besoin de toute façon). Nous pouvons donc en ajouter plusieurs fois.
jusqu'à ce que cette condition soit remplie.Le reste est une simple boucle qui définit l'hexagone. Une observation utile pour cette partie est que les espaces dans l'indentation plus les non-espaces dans le code dans chaque ligne s'additionnent au diamètre.
Il s’avère que nous n’avons pas du tout besoin d’utiliser une double arithmétique (à l’exception de la racine carrée). En raison de la multiplication par 4, il n'y a pas de collision lors de la division par 3, et le résultat souhaité
k
sera le premier à générer une racine carrée entière.la source
Perl,
203200198comprend + 1 pour
-p
courir comme:
echo abc | perl -p file.pl
Une approche très naïve:
;
; code lui-même sous 200 octets maintenant!$s=~/\S+/g
au lieu desplit/\n/,$s
la source
JavaScript (ES6), 162
172Fonction anonyme
La taille de l'hexagone est trouvée en résolvant l'équation de wikipedia
La formule de résolution est fondamentalement
Avec une certaine algèbre et une approximation (merci à @ user18655 aussi) il devient
Plus lisible
Extrait de test (meilleure page complète - durée environ 1 minute)
la source
n=...+1-1e-9|0
au lieu den=Math.ceil(...)
pour enregistrer 2 octets. Vous pouvez également utiliser ES7 et utiliser**0.5
au lieu de,Math.sqrt
mais cela dépend de vous. Je garde généralement mes réponses ES6 car elles fonctionnent dans mon navigateur haha!Pyth,
5251 octetsEssayez-le en ligne. Suite de tests.
Chaque ligne comporte un espace supplémentaire supplémentaire, comme le permet le PO.
Explication
la source
Rétine , 161 octets
Merci à FryAmTheEggman pour la sauvegarde de 2 octets.
Cette réponse est sans compétition. Retina a vu quelques mises à jour depuis ce défi, et je suis à peu près sûr que j'utilise certaines des nouvelles fonctionnalités (bien que je n'ai pas encore vérifié).
Le nombre d'octets suppose un codage ISO 8859-1. La première ligne contient un seul espace. Notez que la plupart
·
sont en fait des points centraux (0xB7).Essayez-le en ligne!
Bien...
Explication
Il semble plus facile de construire la mise en page d’abord en utilisant un seul caractère (
·
dans ce cas), puis de remplir la mise en page résultante avec les caractères saisis. Les principales raisons en sont que l’utilisation d’un seul caractère me permet d’utiliser les références arrières et la répétition de caractères, où la mise en forme directe des entrées nécessiterait des groupes d’équilibrage coûteux.Bien que cela ne semble pas grand chose, cette première étape supprime les espaces de l’entrée.
Nous commençons par ajouter une ligne supplémentaire contenant les
M
points centraux, oùM
est la longueur de l’entrée (après la suppression des espaces).Si la saisie ne comportait qu'un seul caractère, nous supprimons à nouveau le point central. C'est un cas spécial malheureux qui n'est pas couvert par l'étape suivante.
Ceci calcule la longueur de côté requise
N
moins 1. Voici comment cela fonctionne: les nombres hexagonaux centrés sont de la forme3*N*(N-1) + 1
. Étant donné que les nombres triangulaires sontN*(N-1)/2
, cela signifie que les nombres hexagonaux sont six fois un nombre triangulaire plus 1. Cela est pratique, car la correspondance des nombres triangulaires (qui sont vraiment justes1 + 2 + 3 + ... + N
) dans une expression rationnelle est assez facile avec les références directes. La(^·|\2·)*
correspond au plus grand nombre triangulaire possible. En bon bonus,$2
tiendra alors l'index de ce nombre triangulaire. Pour le multiplier par 6, nous le capturons dans un groupe1
et le comparons 5 fois. Nous nous assurons qu'il y a au moins deux autres·
avec le·
et le·+
. De cette façon, l'index du nombre triangulaire trouvé n'augmente pas tant qu'il n'y a pas plus d'un caractère qu'un nombre hexagonal centré.En fin de compte, ce match nous donne deux fois moins que la longueur de côté de l'hexagone requis dans le groupe
$2
, nous écrivons donc cela avec un point central supplémentaire à obtenirN-1
.Cela transforme notre suite de
N-1
points centraux enN-1
espaces, en2N-1
points centraux et en autresN-1
espaces. Notez qu'il s'agit de l'indentation maximale, suivie du diamètre de l'hexagone, suivie de l'indentation à nouveau.Ceci est désagréablement long, mais il nous donne essentiellement toutes les correspondances qui se chevauchent , qui sont soit des
2N-1
caractères a ) et sur la première ligne ou b) la deuxième ligne. Cela étend le résultat de l'étape précédente dans l'hexagone complet, mais étrangement indenté. Par exemple, pour obtenir des informations,12345678
nous obtiendrions:C'est pourquoi nous avons également dû ajouter des espaces lors de l'étape précédente.
Cela corrige l'indentation des lignes après le centre, en indentant de manière répétée toute ligne plus courte que la précédente (en ignorant les espaces de fin), nous obtenons donc ceci:
Maintenant, nous venons d'insérer des espaces avec
Ce qui nous donne:
Ouf, c'est fait.
Il est temps de remplir la chaîne d'entrée dans les points centraux. Cela se fait à l'aide d'une étape de tri. Nous faisons correspondre tous les points centraux et chaque caractère de la dernière ligne et nous les trions en fonction du résultat de la substitution donnée. Cette substitution est vide pour les caractères de la dernière ligne et
·
pour les points centraux; il en résulte que les points centraux sont simplement triés jusqu'à la fin (le tri étant stable). Cela déplace les caractères saisis en place:Il ne reste que deux choses maintenant:
Cela transforme les points centraux en périodes régulières.
Et cela élimine la dernière ligne.
la source
JavaScript (ES6), 144 octets
Où
\n
représente le caractère de nouvelle ligne littéral. Utilise une technique pour créer un hexagone que j'ai déjà utilisée pour plusieurs autres réponses à grille hexagonale . Pour ES7, prendre des racines carrées est légèrement plus court que l’approche récursive:la source
Python 3 , 144 octets
Essayez-le en ligne!
Cela utilise une quantité assez variable d'espaces de premier plan pour des hexagones de tailles différentes, mais la forme générale subsiste.
la source