Dibuja un hexágono ASCII de lado de longitud n

Jan 06 2021

Dado un entero positivo \$n\$generar un hexágono ASCII con longitud de lado diagonal \$n\$, como se muestra en la imagen (tenga en cuenta que hay \$2n\$ _ caracteres en el borde superior)

Ejemplos:

\$n = 1\$

 __
/  \
\__/

\$n = 2\$

  ____
 /    \
/      \
\      /
 \____/

\$n = 5\$

     __________
    /          \
   /            \
  /              \
 /                \
/                  \
\                  /
 \                /
  \              /
   \            /
    \__________/

etc.

El código más corto en bytes gana. Se aplican los métodos habituales de entrada / salida .

Respuestas

11 Razetime Jan 06 2021 at 16:01

Lienzo , 15 9 bytes

 _;1*⁸/∔╬

Pruébelo aquí!

-6 bytes después de arreglar el programa.

Dibuja una cuarta parte del hexágono y se palindromiza cuádruple.

9 xnor Jan 06 2021 at 17:16

Python 2 , 92 bytes

k=n=input()
while 1:a=k^k>>n;print" "*a+"\/_"[k/n-2]+"_ "[-n<k<n]*2*(2*n+~a)+"\_/"[k/n];k-=1

¡Pruébelo en línea!

6 Razetime Jan 06 2021 at 15:54

Carbón , 14 bytes

←×_θ↖θ→↗θ×_θ‖M

¡Pruébelo en línea!

Corrección de +1 byte de solo ASCII.

Dibuja la mitad del hexágono y lo refleja.

6 AZTECCO Jan 07 2021 at 15:50

C (gcc) , 119 109 bytes

a,i,j;f(n){for(i=a+=a=j=n*2;~j;)putchar(!i--?i=a,j--,13:i%(n*3)<n|j%(n*2)?(i-~j-n)%a?(i-j+n)%a?32:92:47:95);}

¡Pruébelo en línea!

  • guardé 2 gracias a @ceilingcat

La siguiente tabla no se actualiza, por lo que los valores pueden diferir, pero el concepto es:

  • tenemos 2 pares de rectas paralelas
        . .
_______.______.________   
  | / \ | .
. | / \ | .
 . / \ |.
  | / \ |
  | \ / |.
 . \ / | .
. | \ / |
__ | ___ \ ________ / ___ | ___   
  | . .

iteramos x, y desde el tamaño hasta 0 y los sumamos para comprobar si se debe imprimir /, restamos para comprobar \, usamos módulo para comprobar ambos paralelos.

    i 65432109876543210. j
 yo + jn ________ 8 
13 + 7-4 => / \ 7 
14 + 6-4 / \ 6 
15 + 5-4 / \ 5 
      / \ 4 
      \ 1 + 3-4 => / 3
       \ 2 + 2-4 / 2
        \ 3 + 1-4 / 1
         \ ________ / 0
5 NahuelFouilleul Jan 07 2021 at 03:22

Perl 5 ( -p), 102 bytes

s/_+/__$&/g,s/^|$/ /gm,s/^ *\S /$& /gm,s-( +)\\ -$&/ $1 \\ \\ $1 /
- for($\=' __ / \ \__/')x--$_}{

¡Pruébelo en línea!

-py }{al final hay un truco para imprimir solo el separador de registros de salida $\al final. Solo funciona para un registro de entrada; el encabezado se utiliza para imprimir todo en un enlace tio.

$\=' __ 
/  \
\__/'   # output record separator initialized with hexagon (size 1)

s/_+/__$&/g,s/^|$/ /gm,s/^ *\S /$& /gm,s-( +)\\ -$&/ $1 \\ \\ $1 /
- # regexes to increase the hexagon by 1

for .. --$_ # to repeat n-1 times where n is the input
5 WheatWizard Jan 08 2021 at 23:56

Haskell , 150 bytes

r=reverse
m(o:c:k)=o:c:c:c:k++" "
f 1=[["\\  /","__ "],["/__\\"]]
f n|[w:i,j]<-map m<$>f(n-1),_:_:k<-r$m w=[r k:w:i,k:j]
h[i,j]=unlines$r<$>r i++j
h.f

¡Pruébelo en línea!

Una versión más recursiva de esta respuesta. La arbitrariedad de este desafío lo hace bastante frustrante.

Explicación

Esta respuesta es un poco difícil de explicar. El desafío es, como ya dije, arbitrario en algunos aspectos, por lo que el código es una especie de nido de símbolos.

Idea

La idea del programa aquí es construir las dos mitades. Es decir, al calcular el n-ésimo hexágono obtenemos las dos mitades del n-1o hexágono y las usamos para hacer el siguiente más grande.

Sin embargo, hay algunas advertencias. Construimos la mitad superior al revés y construimos ambas mitades reflejadas de izquierda a derecha. Hacemos esto porque es conveniente hacerlo de esta manera. No hay ninguna razón profunda para que las cosas sean más breves, incluso si las hace un poco incomprensibles.

Detalles

La primera línea es bastante sencilla y res un alias de reverse. La segunda línea no es tan sencilla. mes una función sin sentido, existe porque es necesario realizarla o una operación similar en algunos lugares. Realmente no tiene un significado semántico. La mejor explicación de lo que hace aquí es el código.

m(o:c:k)=o:c:c:c:k++" "

A partir de aquí comenzamos a llegar a fcuál maneja básicamente toda la lógica. El primer caso fes el caso base, es bastante estándar

f 1=[["\\  /","__ "],["/__\\"]]

Tenga en cuenta que devolvemos una lista de dos elementos en lugar de una tupla. En cualquier programa cuerdo estaríamos usando una tupla ya que está fija en 2 elementos. Sin embargo, más adelante mapearemos ambos argumentos de esto con la misma función. Es difícil hacer eso con una tupla pero fácil con una lista, y la lista no presenta ningún inconveniente, por lo que la usamos.

Luego tenemos el caso inductivo. Primero buscamos el caso anterior y lo mapeamos dos veces m. Esto hace que el hexágono sea 1 unidad más ancho (2 caracteres) y lo mueve media unidad (1 carácter) hacia la derecha (aunque como todo esto está al revés, los caracteres de espacio se agregan a la derecha ). Hacemos coincidir el patrón con esto [w:i,j]porque queremos usarlo wpara hacer nuevas filas más adelante. Hablando de lo que a continuación hacemos las filas. Hacemos esto con una coincidencia de patrón:

_:_:k<-r$m w

Esto es una especie de código sin sentido. Simplemente junta cosas que ya teníamos para producir la salida correcta. ky su reverso forma las nuevas filas, así que las agregamos y devolvemos eso.

Después ftenemos hque convierte la salida de fen una cadena. Deshace todas las transformaciones extravagantes que usamos durante la construcción y las empaqueta para su uso.

Con todo lo que acabamos de componer fy hpara la función final.

5 xnor Jan 11 2021 at 00:58

Haskell , 100 bytes

f n=unlines[q<$>[1..3*n]++[1-n..0]|y<-[-n..n],let q x|abs y==n,x>n='_'|x==y='\\'|x+y==1='/'|1>0=' ']

¡Pruébelo en línea!

Golf : la respuesta de AZTECCO más algunas técnicas nuevas.

La idea principal es que el hexágono es más sencillo si trasplantamos las primeras ncolumnas hasta el final.

|-|
   ______   
  /      \  
 /        \ 
/          \
\          /
 \        / 
  \______/  

         |-|
______      
      \    /
       \  / 
        \/  
        /\  
       /  \  
______/    \

Ahora todos los /y \están en una sola línea, y _todos están a la izquierda de ellos. Esto hace que sea mucho más fácil hacer la estrategia de AZTECCO de determinar el personaje a partir de la coordenada. Para implementar estas coordenadas reetiquetadas, reemplazamos las x-coordenadas [1..4*n]con una versión cíclica y desplazada [1..3*n]++[1-n..0].

4 Neil Jan 06 2021 at 17:08

Retina 0.8.2 , 94 bytes

.+
$* ¶$&$* \G ¶$%'/$`$%_$%_$`\
r` \G
$%`\$'$%_$%_$%'/¶ ^¶( *) $1 $.&$*_$.&$*_$& T` `\_` +/$

¡Pruébelo en línea! El enlace incluye casos de prueba. Explicación:

.+
$* ¶$&$* 

Inserta dos filas de nespacios.

\G 
¶$%'/$`$%_$%_$`\

Convierte la primera fila en los lados superiores del hexágono.

r` \G
$%`\$'$%_$%_$%'/¶

Convierte la segunda fila en los lados inferiores del hexágono.

^¶( *)
$1 $.&$*_$.&$*_$&

Inserte la línea superior.

T` `\_` +/$

Reemplace la línea de fondo.

4 ovs Jan 06 2021 at 16:32

Python 2 , 119114 bytes

i=n=input()
d=0
exec"k=i/n|d;print' '*i+'\_/'[~k]+'_ '[i-d<n]*2*(2*n+~i)+'\_/'[k]\nif i==d:d=i=-1\ni-=d|1;"*(n-~n)

¡Pruébelo en línea!

4 Arnauld Jan 07 2021 at 03:27

JavaScript (ES6),  109107  bytes

w=>(x=0,W=w*4,i=g=y=>~y?`
 /\\_`[x++-W?y*!i|w/x|x>w*3?(x+~y+w)%W?(x+y)%W-w?1:3:2:4:x=i=0&y--]+g(y):'')(w*2)

¡Pruébelo en línea!

Comentado

w => (                        // w = input
  x = 0,                      // initialize x to 0
  W = w * 4,                  // W = total width
  i =                         // initialize i to a non-zero value
  g = y =>                    // g is a recursive function taking y
  ~y ?                        //   if y is not equal to -1:
    `\n /\\_`[                //     list of characters
      x++ - W ?               //     if this is not the end of the row:
        y * !i |              //       if this is neither the first nor the last row
        w / x |               //       or x is less than or equal to w
        x > w * 3 ?           //       or x is greater than w * 3:
          (x + ~y + w) % W ?  //         if (x - y - 1 + w) mod W is not equal to 0:
            (x + y) % W - w ? //           if (x + y) mod W is not equal to w:
              1               //             draw a space
            :                 //           else:
              3               //             draw a '\'
          :                   //         else:
            2                 //           draw a '/'
        :                     //       else:
          4                   //         draw a '_'
      :                       //     else:
        x = i = 0 & y--       //       decrement y, set x and i to 0 and draw a linefeed
    ] + g(y)                  //     append the result of a recursive call
  :                           //   else:
    ''                        //     stop the recursion
)(w * 2)                      // initial call to g with y = w * 2
4 Noodle9 Jan 06 2021 at 21:18

C (gcc) , 194 \$\cdots\$ 149144 bytes

Guardado 13 14 19 bytes gracias a techocat !!!

p(n,c){for(;n--;)printf(L"/\\ _\n"+c);}i;t;f(n){p(n,2);for(i=t=p(2*n,3);i>=p(1,4);t=i/n?--i,1:t)i+=!p(!p(n+i<<!p(!p(n+~i,2),t),t&!i|2),!t)-2*t;}

¡Pruébelo en línea!

Explicación (antes de algunos campos de golf)

p(n,c){for(;n--;)                     // Helper function to print  
         putchar("/\\ _\n"[c]);}      //  one of '/', '\', ' ', '_' , or  
                                      //  newline n times, this function  
                                      //  also returns 0 
i;t;f(n){                             // Main function prints an n hexagon  
        p(n,2);                       // Print n leading spaces for the 1st  
                                      //  line 
        for(                          // Main loop
            i=t=p(2*n,3);             // Set i and t to 0,  
                                      //  and print 2*n '_'s for the 1st line
            i>=p(1,4);                // Loop until i goes below 0, and 
                                      //  print a newline
                                      // At the end of each loop:  
            i+=1-2*t,                 //  increment i for the 1st half  
                                      //   and then decrement i in the 2nd  
            t=i/n?--i,1:t)            //  keep t as t unless i equals n,   
                                      //  then make t 1 and decrement i   
                                      // In the main loop:
                p(n+~i,2),            //  print n-i-1 leading spaces     
                p(1,t),               //  print a '/' in the 1st half and a  
                                      //   '\' in the 2nd    
                p(n+i<<1,t&!i|2),     //  print the 2*(n+i) middle spaces  
                                      //   unless at the bottom print '_'s  
                p(1,!t);              //  print a '\' in the 1st half and a  
                                      //   '/' in the 2nd    
   }  
 
4 ovs Jan 07 2021 at 05:12

05AB1E , 33 29 25 bytes

-4 ( 7 ) bytes gracias a Kevin Cruijssen !

L+<'/úíºI·'_ך»∊¶¡`ðs‡).c

¡Pruébelo en línea!

05AB1E tiene una orden interna del lienzo que podría ser útil, pero es bastante difícil de conseguir trabajo, esto es sólo el espejo órdenes internas ºy y centralizar la orden interna .c.

4 xash Jan 07 2021 at 01:26

J , 50 47 bytes

-3 gracias a Jonah!

' \/_'{~]|."1((0,]+2*|.)@=@i.,.3,3,~0$~<:,])@+:

¡Pruébelo en línea!

((0,]+2*|.)@=@i.  ,.  3,3,~0$~<:,])@+:
     0 0 0 0            3 3 3 3
     1 0 0 2            0 0 0 0
     0 1 2 0            0 0 0 0
     0 2 1 0            0 0 0 0
     2 0 0 1            3 3 3 3

    ]|."1
0 0 3 3 3 3 0 0
0 2 0 0 0 0 1 0
2 0 0 0 0 0 0 1
1 0 0 0 0 0 0 2
0 1 3 3 3 3 2 0

' \/_'{~ 
  ____
 /    \    
/      \    
\      /  
 \____/  
4 Anakhand Jan 06 2021 at 17:25

Python 3.8 (versión preliminar) , 174 bytes

n=int(input())
b,a,s="\/ "
z,f=range(n),lambda c,d,t:((n-1-i)*s+c+2*(n+i)*s+d for i in t)
print(f"{'_'*2*n:^{4*n}}",*f(a,b,z),*f(b,a,z[:0:-1]),f"{b:>{n}}{'_'*2*n}/",sep="\n")

¡Pruébelo en línea!

-1 byte gracias a @Duncan

-8 bytes gracias a @Danis

4 AZTECCO Jan 10 2021 at 18:02

Haskell , 129 120 bytes

g=mod
f n|a<-n*4=[c|y<-[-n..n],x<-[0..a],let c|x<1='\n'|g x(n*3+1)>n,abs y==n='_'|g(x+y)a==1='/'|g(x-y)a<1='\\'|1>0=' ']

¡Pruébelo en línea!

  • guardado 9 gracias a @Wheat Wizard y @xnor.

  • ¡Compruebe la respuesta de @xnor y su gran mejora en el enfoque del problema (evitando líneas de módulo y paralelas)!

  • Equivalente de mi respuesta C

Hacemos coordenadas cartesianas usando la lista de comprensión | y <- [0..n * 2], x <- [0..a]

[c | ..., deje c | ... | ... | ...] y obtenemos el carácter necesario en función de xy o x + y para dibujar líneas.
Usamos módulo para dibujar varias líneas (2)
El caso especial es para el _que no necesita una relación ax / y sino un rango, usé módulo para hacer solo una comparación en >lugar de una a> x> b como

2 vrintle Jan 06 2021 at 15:15

Rubí , 141 bytes

->(n,g=->c,d{(1..n).map{|i|" "*(n-i)+d+" "*2*(n+i-1)+c}},l=g[?/,e=?\\].reverse){[" "*n+?_*n*2,g[e,?/],l[0..-2],l[-1].sub(/ +(?=\/)/,?_*n*2)]}

¡Pruébelo en línea!

Si se permite un guión bajo superior, tomaría bytes un poco menos, mientras que el hexágono es tan bonito como antes ;-)

Rubí , 114 bytes

->n{[" "*n+?_*2*n,(g=->c,d{(1..n).map{|i|" "*(n-i)+c+" "*2*(n+i-1)+d}})[?/,e=?\\],g[e,?/].reverse," "*n+?‾*n*2]}

¡Pruébelo en línea!

2 Makonede Jan 07 2021 at 00:45

05AB1E , 70 bytes

ðש'_¹·×«©¶«©¹'/1Λ¹·Ì'.2Λ¹'\3.Λ«©„./`.;©¶¡Â‚€»`s'.ð:,¹3*>(£„._`:„/\‡,

¡Pruébelo en línea!

2 KjetilS. Jan 07 2021 at 00:54

Perl 5 , 143 bytes

sub f{$n=pop;@b=map{join'',$"x($n-$_),'/','  'x($n+$_-1),'\\',$/}1..$n;join('',$"x$n,$u=__ x$n,$/,@b,map y|/\\|\\/|r,reverse@b)=~s| +/$|$u/|sr}

¡Pruébelo en línea!

sub f{
  $n=pop;             #n = input
  @b=map{             #set array @b to line 2 - n+1
    join'',           #join parts into a line string
    $" x ($n-$_), #space times n-1 '/', #char / ' ' x ($n+$_-1), #space times n+iterator minus 1 '\\', #char \ $/                #char newline
  } 1..$n; #n lines join('', #return string of these joined: $" x $n, #n spaces $u = __ x$n, #n*2 underscores $/,               #char newline
    @b,               #lines 2 to n+1 constructed above
    map y|/\\|\\/|r,  #and bottom part which is the same
      reverse@b       #as top part reversed and /\ rotated
  )=~s| +/$|$u/|sr    #and change last spaces of last line to _'s
}
2 StevenFontanella Jan 07 2021 at 12:31

Haskell , 186168 bytes

-18 bytes con correcciones de xnor y eliminación de espacios innecesarios en la última línea

s=' '
(!)=replicate
e=reverse
h n=unlines$(\m->(n!s++(2*n)!'_'++n!s):e(e<$>m)++init m++[(n-1)!s++'\\':(2*n)!'_'++"/"])$(\i->i!s++'\\':(4*n-2*i-2)!s++'/':i!s)<$>[0..n-1]

¡Pruébelo en línea!

Sin golf:

hex :: Int -> String
hex n = unlines $ first: middle ++ (init $ reverse (map reverse middle)) ++ [last]
  where
    first = replicate n ' ' ++ replicate (2*n) '_' ++ replicate n ' '
    f i = replicate i ' ' ++ "/" ++ replicate (n-i + 2*n + n-i -2) ' ' ++ "\\" ++ replicate i ' '
    middle = map f [n-1,n-2..0]
    last = replicate (n-1) ' ' ++ "\\" ++ replicate (2*n) '_' ++ "/" ++ replicate (n-2) ' '