Dibujar hexágonos ASCII concéntricos

15

Escriba el programa más corto posible que tome un conjunto de enteros positivos distintos y genere una representación ASCII de hexágonos concéntricos con esas longitudes laterales, hechas de barras, guiones bajos, espacios y líneas nuevas.

El programa más corto en bytes contado por https://mothereff.in/byte-counter gana.

Ejemplos

(Se ven mejor con menos espacio entre líneas).

Si la entrada es 1la salida debe ser el hexágono con longitud lateral 1:

 __ 
/  \
\__/

Observe que se usan dos guiones bajos para la parte superior e inferior del hexágono, por lo que está mejor proporcionado.

En general, el hexágono de tamaño N contiene barras diagonales N en cada lado en ángulo y 2 * N subrayados en la parte superior e inferior.

Si la entrada es 1 2la salida, deben ser los hexágonos concéntricos con longitud lateral 1 y 2:

  ____
 / __ \
/ /  \ \
\ \__/ /
 \____/

Si la entrada es 1 3la salida debe ser:

   ______
  /      \
 /   __   \
/   /  \   \
\   \__/   /
 \        /
  \______/

Si la entrada es 1 3 2la salida debe ser:

   ______
  / ____ \
 / / __ \ \
/ / /  \ \ \
\ \ \__/ / /
 \ \____/ /
  \______/

etc.

Reglas de E / S

La entrada debe provenir de la línea de comando o de la entrada estándar, pero puede estar en el formato que sea más conveniente.

Por ejemplo, es posible dar a cada número como un argumento de línea de comandos: > myprogram 1 3 2, o puede pedir al usuario que introduzca los números como una lista con formato previo: [1, 3, 2].

La salida debe ir a stdout o el equivalente más cercano de su idioma.

Reglas Adicionales

  • La entrada siempre será un conjunto de enteros positivos distintos, no necesariamente en ningún orden .
  • La salida debe ...
    • No contiene ningún carácter además de /\ _líneas nuevas.
    • no tener espacios finales o espacios iniciales innecesarios.
    • no contiene nuevas líneas iniciales extrañas, pero puede tener una nueva línea final opcional .
  • Si no se ingresa nada, entonces no se emite nada (excepto posiblemente una nueva línea).
  • Si le ayuda, puede suponer que los enteros de entrada son menores que 2 16 .
Pasatiempos de Calvin
fuente
¿Se 1refiere al hexágono más interno o más externo?
NinjaBearMonkey
@hsl El 1(o cualquier número) se refiere al hexágono con una longitud lateral de 1. (Con la advertencia de que 1 barra oblicua = 2 subraya). Por 1lo tanto , siempre se referirá al hexágono más interno.
Aficiones de Calvin

Respuestas:

4

CJAM, 148 116 109 bytes

Esto tardó mucho más de lo que esperaba. Originalmente, solo quería construir iterativamente el cuadrante superior izquierdo, como en los desafíos de diamantes, y luego obtener el resto de la duplicación. Pero no noté que los guiones bajos no obedecen a la simetría de espejo entre la mitad superior e inferior. Así que tuve que rehacer la mayor parte de eso, para generar la mitad derecha iterativamente y luego solo reflejar una vez (a la izquierda).

S]2[l~]:(f#:+2bW%{_,2/~:T;{IT):T1<'\'/?S?S++}%__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+}fI{)T)2*2$,-*1$W%"\/"_W%er@N}/

Pruébalo aquí.

Un ejemplo de Fibonacci-esque:

8 3 1 5 2
        ________________
       /                \
      /                  \
     /     __________     \
    /     /          \     \
   /     /   ______   \     \
  /     /   / ____ \   \     \
 /     /   / / __ \ \   \     \
/     /   / / /  \ \ \   \     \
\     \   \ \ \__/ / /   /     /
 \     \   \ \____/ /   /     /
  \     \   \______/   /     /
   \     \            /     /
    \     \__________/     /
     \                    /
      \                  /
       \________________/

Explicación:

Como se indicó en la parte superior, empiezo construyendo la mitad derecha de forma iterativa. Es decir, inicialmente solo tengo un espacio en la cuadrícula, y luego para cada anillo posible, rodeo la cuadrícula existente en espacios o un nuevo semi-hexágono.

Una vez hecho esto, reflejo cada línea a la izquierda y la relleno con espacios iniciales para una alineación correcta. Aquí hay un desglose del código:

"Prepare the input and the grid:";
S]2[l~]:(f#:+2bW%
S]                "Push string with a space and wrap it in an array. This is the grid.";
  2               "Push a 2 for future use.";
   [l~]           "Read and evaluate the input, wrap it in an array.";
       :(         "Decrement each number by 1.";
         f#       "Map each number i to 2^i.";
           :+     "Sum them all up.";
             2b   "Get the base two representation.";
               W% "Reverse the array.":
"At this point, the stack has the proto-grid at the bottom, and an array of 1s and
 0s on top, which indicates for each hexagon if it's present or not.";

"Next is a for loop, which runs the block for each of those 0s and 1s, storing the
 actual value in I. This block adds the next semi-hexagon or spaces.";
{ ... }fI

"First, append two characters to all existing lines:";
_,2/~:T;{IT):T1<'\'/?S?S++}%
_                            "Duplicate the previous grid.";
 ,2/                         "Get its length, integer-divide by 2.";
    ~:T;                     "Get the bitwise complement and store it in T. Discard it.";
        {                 }% "Map this block onto each line of the grid.";
         I                   "Push the current hexagon flag for future use.";
          T):T               "Push T, increment, store the new value.";
              1<'\'/?        "If T is less than 1, push \, else push /.";
                     S?      "If the current flag is 0, replace by a space.";
                       S++   "Append a space and add it to the current line.";

"So for hexagons this appends '\ ' to the top half and '/ ' to the bottom half.
 For empty rings, it appends '  ' to all lines.";

"Now add a new line to the top and the bottom:"    
__,2/=,2/I'_S?*_S+a@+\I'/S?S++a+
__                               "Get two copies of the grid.";
  ,2/                            "Get its length, integer-divide by 2.";
     =                           "Get that line - this is always the middle line.";
      ,2/                        "Get ITS length, integer'divide by 2.";
         I'_S?*                  "Get a string of that many _ or spaces depending on the 
                                  current flag.";
               _S+               "Duplicate and a space.";
                  a@+            "Wrap in an array, pull up the grid, and prepend the line.";
                     \           "Swap with the other copy.";
                      I'/S?      "Choose between / and a space depending on the flag.";
                           S++   "Append a space, and add both characters to the line.";
                              a+ "Wrap in an array, and append line to the grid.";

"This is all. Rinse and repeat for all rings. The result will look something like this:

_____ 
     \ 
___   \ 
__ \   \ 
_ \ \   \ 
 \ \ \   \ 
_/ / /   / 
__/ /   / 
___/   / 
      / 
_____/ 

Note that there are still trailing spaces.";

"Finish up all lines. These will not be joined together any more, but simply left
 on the stack in pieces to printed out back-to-back at the end of the program.
 The following runs the given block for each line:";
{ ... } /

"This generates the necessary indentation, then mirrors the lines and puts them
 in the right order:"
)T)2*2$,-*\_W%"\/"_W%er\N
)                         "Slice off that trailing space, but leave it on the stack.";
 T                        "Remember T? That still has something like the the size of
                           the grid from the last iteration. In fact it's N-1, where
                           N is the largest visible hexagon. We can use that to figure
                           out how many spaces we need.";
  )2*                     "Increment and double.";
     2$                   "Copy the current line.";
       ,-                 "Subtract its length from 2*N.";
         *                "Repeat the space that often. This is our indentation.";
          \_              "Swap with the line and duplicate.";
            W%            "Reverse the line.";
              "\/"_W%er   "Replace slashes with backslashes and vice versa.";
                       \  "Swap with the original line.";
                        N "Push a line break.";
Martin Ender
fuente
5

Python - 251, 240, 239 228

l=input()+[0];m=max(l);A=abs;R=range
for j in R(2*m+1):print''.join([[' \\'[(A(j-i+m-1)/2.in l)*(2*m-i)/(j-m-.5)>1],'/'][(A(3*m-i-j)/2.in l)*(i-m-j+.5)/(j-.5-m)>0],'_'][(A(m-j)in l)*(A(2*m-i-.5)<A(m-j))]for i in R(4*m)).rstrip()

Enfoque alternativo (251):

l=input()+[0]
l.sort()
m=max(l)
M=2*m
s=[[' ']*m*4for j in' '*(M+1)]
for i in l:
 I=2*i;s[m-i][M-i:M+i]=s[m+i][M-i:M+i]='_'*I
 for k in range(i):K=k+1;s[m-k][M-I+k]=s[m+K][M+I-K]='/';s[m-k][M+I-K]=s[m+K][M-I+k]='\\'
for t in s:print''.join(t).rstrip()
Falko
fuente
3

APL (222 bytes en UTF-8)

(y 133 caracteres)

Como esta pregunta solicita específicamente la cantidad de bytes en la representación UTF8, tuve que desagruparla un poco para que sea más larga, pero su representación UTF8 es más corta. (En particular, el carácter del operador de trayecto es de tres bytes, mientras ()que solo son dos, por lo que la optimización ya no funciona y también hace que la asignación sea muy costosa).

{⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]

Versión anterior, que es más corta en caracteres (124) pero usa más bytes cuando se representa en UTF-8 (230, que lo pondría en segundo lugar):

M←' '⋄{⎕←⍵/⍨~⌽∧\⌽⍵=M}¨↓⊃{⍵{⍺=M:⍵⋄⍺}¨K↑⍺↑⍨-.5×(K←⍴⍵)+⍴⍺}/{Z⍪⊖⌽Z←↑(⊂(⍵/M),'-'/⍨2×⍵),⍵{('/'↑⍨-⍵),'\',⍨M/⍨2 4-.×⍵⍺}¨⌽⍳⍵}¨N[⍋N←,⎕]

Prueba:

      {⎕←(~⌽∧\⌽⍵=' ')/⍵}¨↓⊃{⍵{⍺=' ':⍵⋄⍺}¨K↑(-.5×(K←⍴⍵)+⍴⍺)↑⍺}/{Z⍪⌽⊖Z←↑(⊂(⍵/' '),(2×⍵)/'-'),⍵{((-⍵)↑'/'),((2 4-.×⍵⍺)/' '),'\'}¨⌽⍳⍵}¨N[⍋N←,⎕]
⎕:
      3 1 5 2
     ----------
    /          \
   /   ------   \
  /   / ---- \   \
 /   / / -- \ \   \
/   / / /  \ \ \   \
\   \ \ \  / / /   /
 \   \ \ -- / /   /
  \   \ ---- /   /
   \   ------   /
    \          /
     ----------
marinus
fuente
Esto no parece cumplir con las especificaciones para los lados superior e inferior (deben ser guiones bajos, no guiones) y, en consecuencia, estar compensado por una línea para los lados inferiores.
Martin Ender
1

Perl 5, 352 (349 bytes + 3 para anE banderas)

Esto probablemente podría jugar mucho más golf ..

@b=sort{$a>$b}@F;map{$_<$j||($j=$_)}@b;$k=++$j;for(;$j--;){$z=$"x$j;for($e=$k;--$e>$j;){$z.=$e~~@b?'/ ':'  '} $z.=($j~~@b?'_':$")x(2*$j);$z.=$_~~@b?' \\':'  'for($j+1..$k-1);say$z}for(0..$k-2){$z=$"x$_;for($e=$k;--$e>$_;){$z.=($e-$k+1?$":'').($e~~@b?'\\':$")}$z.=(($_+1)~~@b?'_':$")x(2*$_+2);$z.=($_~~@b?'/':$").($_-$k+1?$":'')for($_+1..$k-1);say$z}

Sin golf:

# sort list of side lengths 
@b=sort{$a>$b}@F; 
# set $k and $j to max side length + 1
map{$_<$j||($j=$_)}@b;$k=++$j;
for(;$j--;){
  $z=$"x$j;
  for($e=$k;--$e>$j;){$z.=$e~~@b?'/ ':'  '}
  $z.=($j~~@b?'_':$")x(2*$j);
  $z.=$_~~@b?' \\':'  'for($j+1..$k-1);
  say$z
}
for(0..$k-2){
  $z=$"x$_;
  for($e=$k;--$e>$_;){$z.=($e-$k+1?$":'').($e~~@b?'\\':$")}
  $z.=(($_+1)~~@b?'_':$")x(2*$_+2);
  $z.=($_~~@b?'/':$").($_-$k+1?$":'')for($_+1..$k-1);
  say$z 
}

Ejemplo ( 1 5 3 14):

              ____________________________
             /                            \
            /                              \
           /                                \
          /                                  \
         /                                    \
        /                                      \
       /                                        \
      /                                          \
     /                 __________                 \
    /                 /          \                 \
   /                 /   ______   \                 \
  /                 /   /      \   \                 \
 /                 /   /   __   \   \                 \
/                 /   /   /  \   \   \                 \
\                 \   \   \__/   /   /                 /
 \                 \   \        /   /                 /
  \                 \   \______/   /                 /
   \                 \            /                 /
    \                 \__________/                 /
     \                                            /
      \                                          /
       \                                        /
        \                                      /
         \                                    /
          \                                  /
           \                                /
            \                              /
             \____________________________/
es1024
fuente
1

C # - 388 316 bytes

Editar: se modificó la forma en que evita la impresión de espacios finales y agregó LINQ

Programa simple que toma argumentos de línea de comando. Repite cada carácter posible en cada línea de un rectángulo definido por la dimensión máxima del hexágono y lo agrega a la línea actual, antes de recortar las líneas e imprimirlas sucesivamente (produce la nueva línea final opcional).

Código de golf:

using System.Linq;class P{static void Main(string[]A){var I=A.Select(int.Parse);int m=I.Max(),i,j,y,x;for(j=m+1;j-->-m;){var r="";for(i=-2*m-1;++i<2*m-(y=j<0?-j-1:j);)r+="/\\_- "[(x=i<0?-i-1:i)>y&(x+=y)%2>0&x/2<m&&I.Contains(x/2+1)?(i^j)&1:x-y<(y=j<0?-j:j)&y<=m&I.Contains(y)?j<0?2:3:4];System.Console.WriteLine(r);}}}

Código sin golf:

using System.Linq; // all important

class P
{
    static void Main(string[]A)
    {
        var I=A.Select(int.Parse); // create int array

        for(int m=I.Max(),j=m+1,i,y,x;j-->-m;) // for each line...
        {
            var r=""; // current line

            for(i=-2*m-1;++i<2*m-(y=j<0?-j-1:j);) // for each char...
                r+="/\\_- "[// append something to the current line
                (x=i<0?-i-1:i)>y&(x+=y)%2>0&x/2<m&&I.Contains(x/2+1)?
                    (i^j)&1: // slashes as appropriate - I can't work out why this bit works, but it seems to
                x-y<(y=j<0?-j:j)&y<=m&I.Contains(y)?
                    j<0?2:3: // _ or - if required
                4]; // otherwise a space

            System.Console.WriteLine(r); // print current line
        }
    }
}
VisualMelon
fuente
0

APL (Dyalog Classic) , 151 bytes (93 con la codificación APL clásica)

{a0⍴⍨1 0+1 2×n←⌈/⍵⋄a[⊃,/i,¨¨⍵+⍵-1+i←⍳¨⍵]←1⋄a←(⊖⍪-)a⋄a[⊃,/(n+⍵,-⍵),¨¨,⍨i]←2⋄' /_\'[4|(⌽,-)a]}

Pruébalo en línea!

ngn
fuente