Dibuja un hexágono ASCII de lado de longitud n
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
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.
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!
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.
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
Perl 5 ( -p
), 102 bytes
s/_+/__$&/g,s/^|$/ /gm,s/^ *\S /$& /gm,s-( +)\\ -$&/ $1 \\ \\ $1 /
- for($\=' __ / \ \__/')x--$_}{
¡Pruébelo en línea!
-p
y }{
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
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 r
es un alias de reverse
. La segunda línea no es tan sencilla. m
es 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 f
cuál maneja básicamente toda la lógica. El primer caso f
es 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 w
para 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. k
y su reverso forma las nuevas filas, así que las agregamos y devolvemos eso.
Después f
tenemos h
que convierte la salida de f
en 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 f
y h
para la función final.
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 n
columnas 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]
.
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 n
espacios.
\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.
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!
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
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
}
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
.
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
' \/_'{~
____
/ \
/ \
\ /
\____/
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
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
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!
05AB1E , 70 bytes
ðש'_¹·×«©¶«©¹'/1Λ¹·Ì'.2Λ¹'\3.Λ«©„./`.;©¶¡Â‚€»`s'.ð:,¹3*>(£„._`:„/\‡,
¡Pruébelo en línea!
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
}
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) ' '