Déplier le code source Hexagony

52

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 abcdefghse 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 cest égal àabc
  • Seuls les caractères ASCII imprimables ( 32 - 126) sont utilisés, de sorte que seul le Spacecaractère normal est ignoré.
  • Supposons que la longueur de la chaîne est supérieure à 0.
  • C'est du , 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:
   . ? ' .
  ) . @ @ /
 ' / . ! . >
+ = ( < . ! )
 } ( $ > ( <
  % . . . .
   . . . .
Adnan
la source
6
De plus, je ne suis pas sûr que vous souhaitiez être aussi pointilleux, mais les backticks sont ignorés dans le processus de détermination de la largeur du code car ils annotent le caractère suivant. Donc abc`defg, en fait, il deviendrait pastebin.com/ZrdJmHiR
Martin Ender
2
@ MartinBüttner Oh, je ne le savais pas :). Pour ce défi, les backticks ne seront pas ignorés.
Adnan
18
Je veux vraiment voir une réponse dans Hexagony à cette question.
Arcturus
2
@Adnan Une meilleure réponse serait probablement "Vous pouvez supposer que l'entrée ne contient pas de drapeaux de débogage ( `caractères)."
Riking
4
@Ampora Ask et vous recevrez.
Martin Ender

Réponses:

13

Pyth, 57 54 50 49 48 46

V+UJfgh*6sUTlK-zd1_UtJ+*d-JNjd:.[K\.^TJZ=+Z+JN

Suite 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

              ##  Implicit: z=input(); Z=0
Jf...1        ##  Save to J the side length of the hexagon the code fills up
              ##  by finding the first number such that:
gh*6sUT       ##  the the T'th hexagonal number is greater than...
              ##  Computes 6 * T'th triangular number (by using sum 1..T-1) + 1
    lK-zd     ##  ...the length of the code without spaces (also save the string value to K)
V+UJ_UtJ      ##  For loop over N = [0, 1, ..., J-1, ..., 0]:
+*d-JN        ##  append J - N spaces to the front of the line
jd            ##  riffle the result of the next operation with spaces
:.[K\.yJ      ##  slice the string given by K padded to be the length of the Jth hexagon
              ##  number with noops
Z=+Z+JN       ##  from Z to Z + J + N, then set Z to be Z + J + N
FryAmTheEggman
la source
2
Vous devez d’abord prouver que ln (10) * 10 ^ n> 6n-3 (les dérivées) pour n> = 1. C’est facile, car les dérivées de ces expressions sont ln (10) ^ 2 10 ^ n et 6. Puisque 10 ^ n augmente de façon monotone et que 10 ^ 1> 6 * 1, 10 ^ n est supérieur à 6n-3 pour tous n> = 1. Vous pouvez utiliser la même logique pour compléter la preuve pour 10 ^ n et 3n (n-1) +1.
Arcturus
@Ampora Merci, j'avais envisagé d'utiliser des dérivés, mais cela semblait malpropre. Je ne pouvais pas trouver un meilleur moyen cependant, tellement apprécié!
FryAmTheEggman
Heureux de vous aider. Calc peut devenir vraiment moche parfois.
Arcturus
dans le lien pyth.herokuapp.com/?code=etc ci-dessus, je trouve que le compilateur ne fonctionne pas ...
RosLuP
1
@FryAmTheEggman Il existe un moyen très simple de montrer la borne beaucoup plus forte 4 ^ n> 3n (n-1) + 1 pour n> = 1, aucun calcul requis. Il suffit d'utiliser le fait que (1 + 3) ^ n = 1 + 3n + 9n (n-1) / 2 + ... par expansion binomiale. Les premier et troisième termes majorent directement 1 + 3n (n-1), donc l'inégalité est immédiate si le troisième terme existe (c'est-à-dire, pour n> = 2). Cela ne laisse que le cas n = 1, ce qui est trivial puisque la RHS est à 1.
Erick Wong
90

Hexagonie , 271 octets

Je vous présente les premiers 3% d'un auto-interprète Hexagony ...

|./...\..._..>}{<$}=<;>'<..../;<_'\{*46\..8._~;/;{{;<..|M..'{.>{{=.<.).|.."~....._.>(=</.\=\'$/}{<}.\../>../..._>../_....@/{$|....>...</..~\.>,<$/'";{}({/>-'(<\=&\><${~-"~<$)<....'.>=&'*){=&')&}\'\'2"'23}}_}&<_3.>.'*)'-<>{=/{\*={(&)'){\$<....={\>}}}\&32'-<=._.)}=)+'_+'&<

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:

entrez la description de l'image ici

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):

entrez la description de l'image ici
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:

  • Au lieu de résoudre l'équation du nombre hexagonal centré, je calcule simplement des nombres hexagonaux centrés consécutifs jusqu'à ce que l'un soit égal ou supérieur à la longueur de l'entrée. En effet, Hexagony ne dispose pas d’un moyen simple de calculer une racine carrée.
  • Au lieu de rajouter tout de suite l'entrée avec no-ops, je vérifie plus tard si j'ai déjà épuisé les commandes de l'entrée et j'imprime un .si c'est le cas.

Cela signifie que l’idée de base se résume à:

  • Lire et stocker la chaîne d’entrée tout en calculant sa longueur.
  • Trouvez la plus petite longueur de côté N(et le nombre hexagonal centré correspondant hex(N)) pouvant contenir l’entrée entière.
  • Calculez le diamètre 2N-1.
  • Pour chaque ligne, calculez le retrait et le nombre de cellules (dont la somme est égale à 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:

entrez la description de l'image ici

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 -1si 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 est

{&32'-

Ceci é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écutons

=}}})&'+'+)=}

Cette 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 =}:

entrez la description de l'image ici

(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:

entrez la description de l'image ici

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):

entrez la description de l'image ici

Le %dernier caractère lu est le dernier, 29le 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:

=&''3{

Ici, =&copie la longueur (29 dans notre exemple) dans le bord étiqueté longueur . Puis ''3passe à l’arête étiquetée 3 et définit sa valeur sur 3(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 , Ny copie et le décrémente. {=*calcule leur produit en N (N-1) . '*)multiplie cela par la constante 3et 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:

entrez la description de l'image ici

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:

{=&}}}32'"2'=&'*){=&')&}}

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 . '=&copie N-1dans 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:

entrez la description de l'image ici

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

'";{}(

'"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:

entrez la description de l'image ici

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:

entrez la description de l'image ici

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:

entrez la description de l'image 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:

{*46;{{;{{=

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:

entrez la description de l'image ici

Le chemin violet contient ceci:

=M8;~'"=

Le =renverse la direction du député à nouveau. M8définit sa valeur sur 778(car le code de caractère Mis 77et digits s'ajoutent à la valeur actuelle). C’est ce qui se produit 10 (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 .

Martin Ender
la source
19
Je me retrouve souvent à dire cela à propos de l'hexagone: juste whoa.
Conor O'Brien
5
Euh ... mais ... wat ... esprit = soufflé
Adnan
J'espérais que quelqu'un ferait ça et ... Wow. Je suis sans voix. C'est génial.
Arcturus
19
Deuxième étape - écrivez les 97% restants. :)
ASCIIThenANSI
Troisième étape - comme réponse avec le moins d'octets.
Tom M
19

CJam, 56 52 50 48 octets

Ma 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 ...

lS-{_,4*(3/mq:D1%}{'.+}wD{D(2/-z_S*D@-@/(S*N@s}/

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 des 3N(N-1)+1cellules, qui doivent être égales à la longueur du code source k. Nous pouvons résoudre cela Nparce que c'est une simple équation du second degré:

N = 1/2 ± √(1/4 + (k-1)/3)

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ètre D = 2N-1de 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.

lS-     e# Read input and remove spaces.
{       e# While the first block yields something truthy, evaluate the second...
  _,    e#   Duplicate the code and get its length k.
  4*(   e#   Compute 4k-1.
  3/    e#   Divide by 3.
  mq    e#   Take the square root.
  :D    e#   Store this in D, just in case we're done, because when we are, this happens
        e#   to be the diameter of the hexagon.
  1%    e#   Take modulo 1. This is 0 for integers, and non-zero for non-integers.
}{      e# ...
  '.+   e#   Append a no-op to the source code.
}w
D{      e# For every i from 0 to D-1...
  D(2/  e#   Compute (D-1)/2 = N, the side length.
  -z    e#   Subtract that from the current i and get its modulus. That's the size of the
        e#   indentation on this line.
  _S*   e#   Duplicate and get a string with that many spaces.
  D@-   e#   Subtract the other copy from D to get the number of characters of code
        e#   in the current line.
  @/    e#   Pull up the source code and split into chunks of this size.
  (S*   e#   Pull off the first chunk and riffle it with spaces.
  N     e#   Push a linefeed character.
  @s    e#   Pull up the remaining chunks and join them back into a single string.
}/

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é ksera le premier à générer une racine carrée entière.

Martin Ender
la source
8

Perl, 203 200 198

comprend + 1 pour -p

s/\s//g;{($l=y///c)>($h=1+3*++$n*($n-1))&&redo}$s=$_.'.'x($h-$l);for($a=$n;$a<($d=2*$n-1);$a++){$s=~s/.{$a}/$&\n/,$s=reverse($s)for 0..1}$_=join$/,map{(' 'x abs($n-$i++-1)).$_}$s=~/\S+/g;s/\S/ $&/g

courir comme: echo abc | perl -p file.pl

Une approche très naïve:

#!/usr/bin/perl -p

s/\s//g;                            # ignore spaces and EOL etc.
{                                   # find the smallest hex number:
    ($l=y///c)                      # calc string length
    > ($h=1+3*++$n*($n-1))          # 
    && redo                         # (should use 'and', but..)
}

$s = $_                             # save $_ as it is used in the nested for
   . '.' x ($h-$l);                 # append dots to fill hexagon

for ( $a = $n; $a < ($d=2*$n-1); $a++ )
{
        $s=~s/.{$a}/$&\n/,          # split lines
        $s=reverse($s)              # mirror
    for 0..1                        # twice
}

$_ = join$/,                        # join using newline
map {                               # iterate the lines
    (' 'x abs($n-$i++-1)) .$_       # prepend padding
} $s=~/\S+/g;                       # match lines

s/\S/ $&/g                          # prepend spaces to characters
                                    # -p takes care of printing $_

  • mettre à jour 200 enregistrer une affectation variable de variable octet, et 2 autres en omettant final ;; code lui-même sous 200 octets maintenant!
  • mettre à jour 198 économiser 2 octets en utilisant $s=~/\S+/gau lieu desplit/\n/,$s
Kenney
la source
7

JavaScript (ES6), 162 172

Fonction anonyme

La taille de l'hexagone est trouvée en résolvant l'équation de wikipedia

3*n*(n-1)-1 = l

La formule de résolution est fondamentalement

n = ceil(3+sqrt(12*l-3))/6)

Avec une certaine algèbre et une approximation (merci à @ user18655 aussi) il devient

n = trunc(sqrt(l/3-1/12)+1.4999....)
s=>eval("s=s.match(/\\S/g);m=n=Math.sqrt(s.length/3-1/12)+1.49999|0;p=o=``;for(i=n+n;--i;i>n?++m:--m)for(o+=`\n`+` `.repeat(n+n-m),j=m;j--;o+=` `)o+=s[p++]||`.`")

Plus lisible

s=>{
  s=s.match(/\S/g);
  m=n=Math.sqrt(s.length/3-1/12)+1.49999;
  p=o='';
  for(i=n+n; --i; i>n?++m:--m)
    for(o += '\n'+' '.repeat(n+n-m), j=m; j--; o += ' ')
      o+=s[p++]||'.';
  return o
}

Extrait de test (meilleure page complète - durée environ 1 minute)

f=s=>eval("s=s.match(/\\S/g);m=n=Math.sqrt(s.length/3-1/12)+1.49999|0;p=o=``;for(i=n+n;--i;i>n?++m:--m)for(o+=`\n`+` `.repeat(n+n-m),j=m;j--;o+=` `)o+=s[p++]||`.`")

t=0;
r='0';
(T=_=>t++<816?(O.innerHTML=f(r=t%10+r),setTimeout(T,20)):0)()
pre { font-size: 66% }
<pre id=O></pre>

edc65
la source
1
Vous pouvez utiliser n=...+1-1e-9|0au lieu de n=Math.ceil(...)pour enregistrer 2 octets. Vous pouvez également utiliser ES7 et utiliser **0.5au lieu de, Math.sqrtmais cela dépend de vous. Je garde généralement mes réponses ES6 car elles fonctionnent dans mon navigateur haha!
user81655
@ user81655 bon indice, merci
edc65
5

Pyth, 52 51 octets

Jfgh**3TtTl=H-zd1=+H*\.*lHTV+UJt_UJAcH]+JN+*-JNdjdG

Essayez-le en ligne. Suite de tests.

Chaque ligne comporte un espace supplémentaire supplémentaire, comme le permet le PO.

Explication

 f              1          |   find first number n for which
             -zd           |           remove spaces from input
           =H              |         put result in H
          l                |       length of input without spaces
  g                        |     is less than or equal to
   h**3TtT                 |       nth centered hexagonal number
J                          | put result (hexagon side length) in J
                           |
      *lHT                 |      ten times length of input without spaces
   *\.                     |   that amount of dots
=+H                        | append to H
                           |
  UJ                       |    numbers 0 up to side length - 1
 +  t_UJ                   |   add numbers side length - 2 down to 0
V                          | loop over result
            +JN            |       current loop number + side length
         cH]               |     split to two parts at that position
        A                  |   put parts to G and H
                 -JN       |       side length - current loop number - 1
                *   d      |     that many spaces
                     jdG   |     join code on the line (G) by spaces
               +           |   concatenate parts and print
PurkkaKoodari
la source
5

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).

 

^
$._$*·¶
^·¶
¶
((^·|\2·)*)·\1{5}·+
$2·
^·*
$.&$* ·$&$&$.&$* 
M!&m`(?<=(?= *(·)+)^.*)(?<-1>.)+(?(1)!)|^.+$
+m`^( *·+)· *¶(?=\1)
$& 
·
 ·
O$`(·)|\S
$1
·
.
G-2`

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 Mpoints centraux, où Mest 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.

((^·|\2·)*)·\1{5}·+
$2·

Ceci calcule la longueur de côté requise Nmoins 1. Voici comment cela fonctionne: les nombres hexagonaux centrés sont de la forme 3*N*(N-1) + 1. Étant donné que les nombres triangulaires sont N*(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 justes 1 + 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, $2tiendra alors l'index de ce nombre triangulaire. Pour le multiplier par 6, nous le capturons dans un groupe 1et 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 à obtenir N-1.

^·*
$.&$* ·$&$&$.&$* 

Cela transforme notre suite de N-1points centraux en N-1espaces, en 2N-1points centraux et en autres N-1espaces. Notez qu'il s'agit de l'indentation maximale, suivie du diamètre de l'hexagone, suivie de l'indentation à nouveau.

M!&m`(?<=(?= *(·)+)^.*)(?<-1>.)+(?(1)!)|^.+$

Ceci est désagréablement long, mais il nous donne essentiellement toutes les correspondances qui se chevauchent , qui sont soit des 2N-1caractè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, 12345678nous obtiendrions:

  ···
 ····
·····
···· 
···  
12345678

C'est pourquoi nous avons également dû ajouter des espaces lors de l'étape précédente.

+m`^( *·+)· *¶(?=\1)
$& 

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:

  ···
 ····
·····
 ···· 
  ···  
12345678

Maintenant, nous venons d'insérer des espaces avec

·
 ·

Ce qui nous donne:

   · · ·
  · · · ·
 · · · · ·
  · · · · 
   · · ·  
12345678

Ouf, c'est fait.

O$`(·)|\S
$1

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:

   1 2 3
  4 5 6 7
 8 · · · ·
  · · · · 
   · · ·  
········

Il ne reste que deux choses maintenant:

·
.

Cela transforme les points centraux en périodes régulières.

G-2`

Et cela élimine la dernière ligne.

Martin Ender
la source
1

JavaScript (ES6), 144 octets

(s,n=1,l=0,p=0,m=s.match(/\S/g))=>m[n]?f(s,n+6*++l,l):[...Array(l+l+1)].map((_,i,a)=>a.map((_,j)=>j<l-i|j<i-l?``:m[p++]||`.`).join` `).join`\n`

\nrepré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 à . Pour ES7, prendre des racines carrées est légèrement plus court que l’approche récursive:

(s,p=0,m=s.match(/\S/g),l=(~-m.length/3)**.5+.5|0)=>[...Array(l+l+1)].map((_,i,a)=>a.map((_,j)=>j<l-i|j<i-l?``:m[p++]||`.`).join` `).join`\n`
Neil
la source
1

Python 3 , 144 octets

c=input().replace(' ','')
n=x=1
while x<len(c):x+=n*6;n+=1
c=c.ljust(x,'.')
while c:print(' '*(x-n)+' '.join(c[:n]));c=c[n:];n-=(len(c)<x/2)*2-1

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.

Jo King
la source