Desplegando el código fuente de Hexagony


52

Introducción

Si no está familiarizado con Hexagony , es un lenguaje esotérico creado por Martin Büttner. La cuestión es que este lenguaje acepta múltiples formas para el programa. Los siguientes programas son todos equivalentes:

abcdefg

y

 a b
c d e
 f g

Básicamente, el código se ha enrollado en un hexágono regular. Pero tenga en cuenta que agregar un nuevo comando al código, que abcdefghsería el resultado en el siguiente programa:

  a b c
 d e f g
h . . . .
 . . . .
  . . .

Como puede ver, el primer paso es enrollar el código en un hexágono, y luego el hexágono se completa con no-ops ( .) hasta el siguiente número hexagonal centrado .

Su tarea es simple, cuando se le asigna una cadena (el código fuente), genera el código fuente completo del hexágono.

Las normas

  • Puede proporcionar un programa o una función.
  • Se permite el espacio en blanco inicial, pero solo cuando el hexágono no se deforma
  • Se permite el espacio en blanco al final.
  • Tenga en cuenta que los espacios en blanco en el programa se ignoran . Entonces a b ces igual aabc
  • Solo 32 - 126se utilizan los caracteres ASCII imprimibles ( ), por lo que solo Spacese ignora el carácter normal .
  • Suponga que la longitud de la cadena es mayor que 0.
  • Este es el , por lo que gana el envío con la menor cantidad de bytes.

Casos de prueba

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:
   . ? ' .
  ) . @ @ /
 ' / . ! . >
+ = ( < . ! )
 } ( $ > ( <
  % . . . .
   . . . .

66
Además, no estoy seguro de si quieres ser tan exigente, pero los backticks se ignoran en el proceso de determinar el ancho del código porque anotan el siguiente carácter. Así abc`defgque en realidad se convertiría en pastebin.com/ZrdJmHiR
Martin Ender

2
@ MartinBüttner Oh, no lo sabía :). Para este desafío, los backticks no serán ignorados.
Adnan

18
Realmente quiero ver una respuesta en Hexagony para esta pregunta.
Arcturus

2
@Adnan Probablemente una mejor respuesta sería "Puede suponer que la entrada no contiene indicadores de depuración ( `caracteres)".
Riking

44
@Ampora Ask y recibirás.
Martin Ender

Respuestas:


13

Pyth, 57 54 50 49 48 46

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

Banco de pruebas

Imprime un espacio inicial en cada línea.

Esta versión requiere una prueba de que 10 ^ n> = 3n (n - 1) + 1 para todo n> = 1 . Gracias a ANerdI y ErickWong por proporcionar pruebas.

Siguiendo estas desigualdades: 10 ^ n> (1 + 3) ^ n = 1 + 3n + 9n (n - 1) + ...> 3n (n - 1) + 1 se puede ver fácilmente que esto es correcto para n> = 2 . Examinar el caso n = 1 es bastante trivial, dando 10> 1 .

Alternativamente, tomar las derivadas de estas ecuaciones dos veces muestra que 10 ^ n tiene una segunda derivada mayor para todos n> = 1 , que luego se puede conectar en cascada a las primeras derivadas, y finalmente a las ecuaciones originales.

Explicación

              ##  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

2
Primero debes probar que ln (10) * 10 ^ n> 6n-3 (las derivadas) para n> = 1. Esto es fácil, ya que las derivadas de estas expresiones son ln (10) ^ 2 10 ^ ny 6. Como 10 ^ n aumenta monotónicamente y 10 ^ 1> 6 * 1, 10 ^ n es mayor que 6n-3 para todos n> = 1. Puede usar la misma lógica para completar la prueba para 10 ^ ny 3n (n-1) +1.
Arcturus

@Ampora Gracias, había considerado usar derivados, pero parecía impuro. Sin embargo, no pude encontrar una mejor manera, ¡muy apreciado!
FryAmTheEggman

Encantado de ayudar. Calc puede ponerse realmente feo a veces.
Arcturus

en el enlace pyth.herokuapp.com/?code=etc arriba encuentro que el compilador no se ejecuta ...
RosLuP

1
@FryAmTheEggman Hay una manera muy fácil de mostrar el límite mucho más fuerte 4 ^ n> 3n (n-1) + 1 para n> = 1, no se requiere cálculo. Simplemente use el hecho de que (1 + 3) ^ n = 1 + 3n + 9n (n-1) / 2 + ... por expansión binomial. Los términos primero y tercero se especializan directamente en 1 + 3n (n-1), por lo que la desigualdad es inmediata si existe el tercer término (es decir, para n> = 2). Esto deja solo el caso n = 1, que es trivial ya que el RHS es 1.
Erick Wong

90

Hexagonía , 271 bytes.

Te presento el primer 3% de un autointerpretador de Hexagony ...

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

Pruébalo en línea! También puede ejecutarlo en sí mismo, pero tardará entre 5 y 10 segundos.

En principio, esto podría encajar en la longitud lateral 9 (para una puntuación de 217 o menos), porque esto usa solo 201 comandos, y la versión no escrita que escribí primero (en la longitud lateral 30) solo necesitaba 178 comandos. Sin embargo, estoy bastante seguro de que tomaría una eternidad hacer que todo encajara, así que no estoy seguro de si realmente lo intentaré.

También debería ser posible jugar golf un poco en tamaño 10 evitando el uso de las últimas una o dos filas, de modo que se puedan omitir las operaciones no finales, pero eso requeriría una reescritura sustancial, como una de las primeras rutas une hace uso de la esquina inferior izquierda.

Explicación

Comencemos desplegando el código y anotando las rutas de flujo de control:

ingrese la descripción de la imagen aquí

Eso sigue siendo bastante desordenado, así que aquí está el mismo diagrama para el código "no golfista" que escribí primero (de hecho, esto es 20 de longitud lateral y originalmente escribí el código en 30 de longitud lateral pero fue tan escaso que no sería no mejora la legibilidad en absoluto, así que lo compacté solo un poco para que el tamaño sea un poco más razonable):

ingrese la descripción de la imagen aquí
Haga clic para una versión más grande.

Los colores son exactamente los mismos, aparte de algunos detalles menores, los comandos sin control de flujo también son exactamente los mismos. Así que explicaré cómo funciona esto en función de la versión sin golf, y si realmente quieres saber cómo funciona el golf, puedes verificar qué partes corresponden a cuáles en el hexágono más grande. (El único inconveniente es que el código de golf comienza con un espejo para que el código real comience en la esquina derecha hacia la izquierda).

El algoritmo básico es casi idéntico a mi respuesta CJam . Hay dos diferencias:

  • En lugar de resolver la ecuación de números hexagonales centrados, solo calculo números hexagonales centrados consecutivos hasta que uno sea igual o mayor que la longitud de la entrada. Esto se debe a que Hexagony no tiene una manera simple de calcular una raíz cuadrada.
  • En lugar de rellenar la entrada con no-ops de inmediato, verifico más tarde si ya he agotado los comandos en la entrada e imprimo un .en su lugar si lo he hecho.

Eso significa que la idea básica se reduce a:

  • Lea y almacene la cadena de entrada mientras calcula su longitud.
  • Encuentre la longitud lateral más pequeña N(y el número hexagonal centrado correspondiente hex(N)) que puede contener toda la entrada.
  • Calcule el diámetro 2N-1.
  • Para cada línea, calcule la sangría y el número de celdas (que suman 2N-1). Imprima la sangría, imprima las celdas ( .si la entrada ya está agotada), imprima un salto de línea.

Tenga en cuenta que solo hay no-ops, por lo que el código real comienza en la esquina izquierda (el $, que salta sobre el >, por lo que realmente comenzamos en el ,camino en gris oscuro).

Aquí está la cuadrícula de memoria inicial:

ingrese la descripción de la imagen aquí

Entonces, el puntero de la memoria comienza en la entrada etiquetada en el borde , apuntando hacia el norte. ,lee un byte de STDIN o un -1si hemos golpeado EOF en ese borde. Por lo tanto, <justo después es condicional si hemos leído toda la entrada. Permanezcamos en el bucle de entrada por ahora. El siguiente código que ejecutamos es

{&32'-

Esto escribe un 32 en el espacio etiquetado como borde y luego lo resta del valor de entrada en el borde etiquetado como diff . Tenga en cuenta que esto nunca puede ser negativo porque estamos garantizados de que la entrada contiene solo ASCII imprimible. Será cero cuando la entrada sea un espacio. (Como lo señala Timwi, esto aún funcionaría si la entrada pudiera contener saltos de línea o pestañas, pero también eliminaría todos los demás caracteres no imprimibles con códigos de caracteres menores que 32). En ese caso, <desvía el puntero de instrucción (IP) a la izquierda y se toma el camino gris claro. Ese camino simplemente restablece la posición del MP {=y luego lee el siguiente carácter, por lo tanto, se omiten los espacios. De lo contrario, si el personaje no era un espacio, ejecutamos

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

Este primero se mueve alrededor del hexágono a través del borde de longitud hasta su lado opuesto al borde de diferencia , con =}}}. Luego copia el valor de enfrente del borde de longitud en el borde de longitud , y lo incrementa con )&'+'+). Veremos en un segundo por qué esto tiene sentido. Finalmente, movemos una nueva ventaja con =}:

ingrese la descripción de la imagen aquí

(Los valores de borde particulares son del último caso de prueba dado en el desafío.) En este punto, el ciclo se repite, pero con todo desplazado un hexágono al noreste. Entonces, después de leer otro personaje, obtenemos esto:

ingrese la descripción de la imagen aquí

Ahora puede ver que estamos escribiendo gradualmente la entrada (menos espacios) a lo largo de la diagonal noreste, con los caracteres en cada otro borde, y la longitud hasta ese carácter se almacena paralela al borde etiquetado como longitud .

Cuando hayamos terminado con el bucle de entrada, la memoria se verá así (donde ya he etiquetado algunos bordes nuevos para la siguiente parte):

ingrese la descripción de la imagen aquí

El %es el último carácter que leemos, el 29es el número de caracteres no espaciales que leemos. Ahora queremos encontrar la longitud lateral del hexágono. Primero, hay un código de inicialización lineal en la ruta verde / gris oscuro:

=&''3{

Aquí, =&copia la longitud (29 en nuestro ejemplo) en el borde etiquetado como longitud . Luego se ''3mueve al borde etiquetado como 3 y establece su valor en 3(que solo necesitamos como constante en el cálculo). Finalmente se {mueve al borde etiquetado N (N-1) .

Ahora entramos en el bucle azul. Este bucle se incrementa N(almacenado en la celda etiquetada como N ) y luego calcula su número hexagonal centrado y lo resta de la longitud de entrada. El código lineal que hace eso es:

{)')&({=*'*)'-

Aquí, {)se mueve a y en incrementos de N . ')&(se mueve al borde etiquetado como N-1 , copia Nallí y lo disminuye. {=*calcula su producto en N (N-1) . '*)multiplica eso por la constante 3e incrementa el resultado en el borde etiquetado como hexadecimal (N) . Como se esperaba, este es el enésimo número hexagonal centrado. Finalmente '-calcula la diferencia entre eso y la longitud de entrada. Si el resultado es positivo, la longitud del lado aún no es lo suficientemente grande y el bucle se repite (donde }}mueve el MP nuevamente al borde etiquetado como N (N-1) ).

Una vez que la longitud lateral es lo suficientemente grande, la diferencia será cero o negativa y obtenemos esto:

ingrese la descripción de la imagen aquí

En primer lugar, ahora existe el camino verde lineal realmente largo que realiza algunas inicializaciones necesarias para el bucle de salida:

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

Las {=&aperturas de copiar el resultado en el diff borde en la longitud del borde, ya que después no necesitamos algo no positivo. }}}32escribe un 32 en el espacio etiquetado como borde . '"2escribe un constante 2 en el borde sin marcar arriba de diff . '=&copias N-1en el segundo borde con la misma etiqueta. '*)lo multiplica por 2 y lo incrementa para que obtengamos el valor correcto en el borde etiquetado 2N-1 en la parte superior. Este es el diámetro del hexágono. {=&')&copia el diámetro en el otro borde etiquetado como 2N-1 . Finalmente }}regresa al borde etiquetado 2N-1 en la parte superior.

Vuelva a etiquetar los bordes:

ingrese la descripción de la imagen aquí

El borde en el que estamos actualmente (que todavía mantiene el diámetro del hexágono) se usará para iterar sobre las líneas de la salida. El borde etiquetado como sangría calculará cuántos espacios se necesitan en la línea actual. Las celdas etiquetadas de borde se usarán para iterar sobre el número de celdas en la línea actual.

Ahora estamos en el camino rosado que calcula la sangría . ('-disminuye el iterador de líneas y lo resta de N-1 (en el borde de sangría ). La rama corta azul / gris en el código simplemente calcula el módulo del resultado ( ~niega el valor si es negativo o cero, y no sucede nada si es positivo). El resto del camino rosado es el "-~{que resta la sangría del diámetro al borde de las celdas y luego vuelve al borde de la sangría .

El camino amarillo sucio ahora imprime la sangría. El contenido del bucle es realmente justo

'";{}(

Donde se '"mueve al borde del espacio , lo ;imprime, {}vuelve al sangrado y lo (disminuye.

Cuando hayamos terminado con eso, el (segundo) camino gris oscuro busca el siguiente carácter para imprimir. Los =}movimientos en posición (lo que significa, en el borde de las celdas , apuntando hacia el sur). Luego tenemos un bucle muy apretado del {}cual simplemente se mueve dos bordes hacia abajo en la dirección suroeste, hasta llegar al final de la cadena almacenada:

ingrese la descripción de la imagen aquí

¿Te das cuenta de que he vuelto a etiquetar un borde allí EOF? . Una vez que hayamos procesado este carácter, haremos que ese borde sea negativo, de modo que el {}ciclo termine aquí en lugar de la siguiente iteración:

ingrese la descripción de la imagen aquí

En el código, estamos al final del camino gris oscuro, donde 'retrocede un paso hacia el carácter de entrada. Si la situación es uno de los dos últimos diagramas (es decir, todavía hay un carácter de la entrada que aún no hemos impreso), entonces estamos tomando el camino verde (el inferior, para las personas que no son buenas con el verde y azul). Ese es bastante simple: ;imprime el personaje en sí. 'se mueve al borde del espacio correspondiente que todavía tiene un 32 de antes e ;imprime ese espacio. Entonces {~hace nuestro EOF? negativo para la siguiente iteración, 'retrocede un paso para que podamos volver al extremo noroeste de la cadena con otro }{bucle cerrado . Que termina en la longitudcelda (la no positiva debajo del hex (N) . Finalmente se }mueve de regreso al borde de las celdas .

Sin embargo, si ya hemos agotado la entrada, ¿el bucle que busca EOF? en realidad terminará aquí:

ingrese la descripción de la imagen aquí

En ese caso, se 'mueve a la celda de longitud , y en su lugar estamos tomando el camino azul claro (superior), que imprime un no-op. El código en esta rama es lineal:

{*46;{{;{{=

El {*46;escribe un 46 en el borde marcado no-op y lo imprime (es decir, un período). Luego se {{;mueve al borde del espacio e imprime eso. El {{=retrocede al borde de las celdas para la siguiente iteración.

En este punto, los caminos se unen y (disminuye el borde de las celdas . Si el iterador aún no es cero, tomaremos el camino gris claro, que simplemente invierte la dirección del MP =y luego busca el siguiente carácter para imprimir.

De lo contrario, hemos llegado al final de la línea actual, y la IP tomará el camino púrpura en su lugar. Así es como se ve la cuadrícula de memoria en ese punto:

ingrese la descripción de la imagen aquí

El camino púrpura contiene esto:

=M8;~'"=

El =revierte la dirección del MP nuevamente. M8establece el valor de establece en 778(porque el código de caracteres de Mis 77y dígitos se agregarán al valor actual). Esto sucede 10 (mod 256), así que cuando lo imprimimos ;, obtenemos un salto de línea. Luego ~hace que el borde sea negativo nuevamente, '"retrocede al borde de las líneas e =invierte el MP una vez más.

Ahora, si el borde de las líneas es cero, hemos terminado. La IP tomará la ruta roja (muy corta), donde @termina el programa. De lo contrario, continuamos en el camino púrpura que vuelve al rosa para imprimir otra línea.


Controle los diagramas de flujo creados con HexagonyColorer de Timwi . Diagramas de memoria creados con el depurador visual en su IDE esotérico .


19
Me encuentro diciendo esto muchas veces sobre respuestas hexagonales: solo whoa.
Conor O'Brien

55
Huh ... pero ... wat ... mente = soplado
Adnan

Esperaba que alguien hiciera esto y ... Wow. Estoy sin palabras. Eso es genial.
Arcturus

19
Paso dos: escribe el otro 97%. :)
ASCIIThenANSI

Paso tres: como la respuesta con la menor cantidad de bytes.
Tom M

19

CJam, 56 52 50 48 bytes

Mi primer pensamiento fue: "¡Oye, ya tengo código para esto!" Pero entonces no podía molestarme en juntar las piezas necesarias del código Ruby, especialmente porque no parecían muy adecuadas para el golf. Así que intenté algo más en CJam en su lugar ...

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

Pruébalo aquí.

Explicación

Un poco de matemática sobre números hexagonales centrados primero. Si el hexágono regular tiene longitud lateral N, contendrá 3N(N-1)+1celdas, que deben ser iguales a la longitud del código fuente k. Podemos resolver eso Nporque es una ecuación cuadrática simple:

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

Podemos ignorar la raíz negativa, porque eso da un N. negativo Para que esto tenga una solución, necesitamos que la raíz cuadrada sea un medio entero. O, en otras palabras, √(1 + 4(k-1)/3) = √((4k-1)/3)debe ser un número entero (por suerte, este número entero es el diámetro D = 2N-1del hexágono, que necesitaremos de todos modos). Por lo tanto, podemos agregar una sola repetidamente .hasta que se cumpla esa condición.

El resto es un bucle simple que presenta el hexágono. Una observación útil para esta parte es que los espacios en la sangría más los no espacios en el código en cada línea se suman al diámetro.

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.
}/

Resulta que no necesitamos usar aritmética doble (excepto la raíz cuadrada). Debido a la multiplicación por 4, no hay colisiones al dividir por 3, y el deseado kserá el primero en producir una raíz cuadrada entera.


8

Perl, 203 200 198

incluye + 1 para -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

correr como: echo abc | perl -p file.pl

Un enfoque muy ingenuo:

#!/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 $_

  • la actualización 200 guarda una asignación de variable móvil de byte y otras 2 omitiendo final ;; código en sí bajo 200 bytes ahora!
  • actualizar 198 guardar 2 bytes utilizando en $s=~/\S+/glugar desplit/\n/,$s

7

JavaScript (ES6), 162 172

Función anónima

El tamaño del hexágono se encuentra resolviendo la ecuación de wikipedia

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

La fórmula de resolución es básicamente

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

Con algo de álgebra y algo de aproximación (gracias a @ user18655 también) se convierte en

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++]||`.`")

Más legible

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
}

Fragmento de prueba (mejor página completa - tiempo de ejecución ~ 1 minuto)

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>


1
Puede usar en n=...+1-1e-9|0lugar de n=Math.ceil(...)guardar 2 bytes. También puede usar ES7 y usar en **0.5lugar de, Math.sqrtpero eso depende de usted. Normalmente solo guardo mis respuestas ES6 porque funcionan en mi navegador jaja!
user81655

@ user81655 buena pista, gracias
edc65

5

Pyth, 52 51 bytes

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

Pruébalo en línea. Banco de pruebas.

Cada línea tiene un espacio inicial adicional, según lo permitido por el OP.

Explicación

 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

5

Retina , 161 bytes

Gracias a FryAmTheEggman por guardar 2 bytes.

Esta respuesta no es competitiva. Retina ha visto algunas actualizaciones desde este desafío, y estoy bastante seguro de que estoy usando algunas de las funciones más nuevas (aunque no lo he comprobado).

El recuento de bytes asume la codificación ISO 8859-1. La primera línea contiene un solo espacio. Tenga en cuenta que la mayoría ·son puntos centrales (0xB7).

 

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

Pruébalo en línea!

Bien...

Explicación

Parece más fácil construir el diseño primero usando un solo carácter ( ·en este caso) y luego llenar el diseño resultante con los caracteres de entrada. Las razones principales para esto son que el uso de un solo carácter me permite hacer uso de referencias inversas y la repetición de caracteres, donde el diseño de la entrada directamente requeriría costosos grupos de equilibrio.

 

Aunque no parece mucho, esta primera etapa elimina espacios de la entrada.

^
$._$*·¶

Comenzamos anteponiendo una línea adicional que contiene Mpuntos centrales, donde Mestá la longitud de la entrada (después de eliminar espacios).

^·¶
¶

Si la entrada era un solo carácter, eliminamos ese punto central nuevamente. Este es un caso especial desafortunado que no está cubierto en la siguiente etapa.

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

Esto calcula la longitud del lado requerido Nmenos 1. Así es como funciona: los números hexagonales centrados son de la forma 3*N*(N-1) + 1. Dado que los números triangulares son N*(N-1)/2, eso significa que los números hexagonales son seis veces un número triangular más 1. Eso es conveniente porque hacer coincidir los números triangulares (que son realmente justos 1 + 2 + 3 + ... + N) en una expresión regular es bastante fácil con referencias directas. El (^·|\2·)*coincide con el número triangular más grande que puede. Como un buen bono, $2mantendrá el índice de este número triangular. Para multiplicarlo por 6, lo capturamos en grupo 1y lo combinamos otras 5 veces. Nos aseguramos de que haya al menos dos más ·con el ·y el·+. De esta manera, el índice del número triangular encontrado no aumenta hasta que haya un carácter más que un número hexagonal centrado.

Al final, esta coincidencia nos da dos menos que la longitud del lado del hexágono requerido en el grupo $2, por lo que escribimos de nuevo junto con un punto central más para obtener N-1.

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

Esto convierte nuestra cadena de N-1puntos centrales en N-1espacios, 2N-1puntos centrales y otros N-1espacios. Tenga en cuenta que esta es la sangría máxima, seguida del diámetro del hexágono, seguida de la sangría nuevamente.

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

Esto es desagradablemente largo, pero básicamente solo nos da coincidencias superpuestas , que son a) 2N-1caracteres largos y en la primera línea ob) la segunda línea. Esto expande el resultado de la etapa anterior al hexágono completo, pero extrañamente sangrado. Por ejemplo, para la entrada 12345678obtendríamos:

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

Es por eso que también necesitábamos agregar espacios en la etapa anterior.

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

Esto corrige la sangría de las líneas después del centro, al sangrar repetidamente cualquier línea que sea más corta que la anterior (ignorando los espacios finales), por lo que obtenemos esto:

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

Ahora solo insertamos algunos espacios con

·
 ·

Lo que nos da:

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

Uff, ya está hecho.

O$`(·)|\S
$1

Es hora de llenar la cadena de entrada en los puntos centrales. Esto se hace con la ayuda de una etapa de clasificación. Unimos todos los puntos centrales y cada personaje en la última línea, y los clasificamos por el resultado de la sustitución dada. Esa sustitución está vacía para los caracteres en la última línea y ·para los puntos centrales, por lo que sucede que los puntos centrales simplemente se ordenan hasta el final (ya que la clasificación es estable). Esto mueve los caracteres de entrada a su lugar:

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

Solo quedan dos cosas ahora:

·
.

Esto convierte los puntos centrales en períodos regulares.

G-2`

Y esto descarta la última línea.


1

JavaScript (ES6), 144 bytes

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

Donde \nrepresenta el carácter literal de nueva línea. Utiliza una técnica para crear un hexágono que he usado previamente en varias otras respuestas de . Para ES7, tomar raíces cuadradas resulta un poco más corto que el enfoque recursivo:

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

1

Python 3 , 144 bytes

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

Pruébalo en línea!

Esto utiliza una cantidad bastante variable de espacios en blanco iniciales para hexágonos de diferentes tamaños, pero la forma general sobrevive.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.