language agnostic - Código Golf: Colmena
language-agnostic code-golf (14)
El reto
El código más corto por recuento de caracteres que generará una colmena a partir de la entrada del usuario.
Una colmena se define como una cuadrícula de hexágonos en un tamaño ingresado por el usuario como dos números positivos mayores que cero (no es necesario validar la entrada). El primer número ( W
) representa el ancho de la colmena - o - cuántos hexágonos hay en cada fila. El segundo número ( H
) representa la altura de la colmena - o - cuántos hexágonos hay en cada columna.
Un solo hexágono está formado por tres caracteres ASCII: _
, /
y /
, y tres líneas:
__
/ /
/__/
Los hexágonos se completan: la primera columna de la colmena será "baja", y la segunda será alta, alternando y repitiendo en el mismo patrón formando W hexágonos. Esto se repetirá H veces para formar un total de hexágonos WxH.
Casos de prueba:
Input:
1 1
Output:
__
/ /
/__/
Input:
4 2
Output:
__ __
__/ /__/ /
/ /__/ /__/
/__/ /__/ /
/ /__/ /__/
/__/ /__/
Input:
2 5
Output:
__
__/ /
/ /__/
/__/ /
/ /__/
/__/ /
/ /__/
/__/ /
/ /__/
/__/ /
/ /__/
/__/
Input:
11 3
Output:
__ __ __ __ __
__/ /__/ /__/ /__/ /__/ /__
/ /__/ /__/ /__/ /__/ /__/ /
/__/ /__/ /__/ /__/ /__/ /__/
/ /__/ /__/ /__/ /__/ /__/ /
/__/ /__/ /__/ /__/ /__/ /__/
/ /__/ /__/ /__/ /__/ /__/ /
/__/ /__/ /__/ /__/ /__/ /__/
El recuento de códigos incluye entrada / salida (es decir, programa completo).
C89 - 261 caracteres necesarios
Todos los espacios en blanco se pueden eliminar. Mi solución utiliza la rotación del tablero ...
x,y,W,h,B[999],*a,*b,*c,*d;
main(w){
for(scanf("%d%d",&h,&w);y<h;y++,*b++ = *c++ = 63)
for(x=0,
W=w*2+2-(h==1),
a=B+y*W*3+y%2,
b=a+W,
c=b+W,
d=c+W;x++<w;)
*a++ = 60,
*a++ = *d++ = 15,
*b++ = *c++ = 63,
*b++ = *c++ = 0,
*d++ = 60;
for(x=W;--x>=0;puts(""))
for(y=0;y<h*3+1;putchar(B[x+y++*W]+32));
}
F #, 303 caracteres
let[|x;y|]=System.Console.ReadLine().Split([|'' ''|])
let p=printf
let L s o e=p"%s"s;(for i in 1..int x do p"%s"(if i%2=1 then o else e));p"/n"
if int x>1 then L" "" "" __ ";L" ""__""/ //"
else L" ""__"""
for i in 1..int y-1 do(L"/"" //""__/";L"//""__/"" //")
L"/"" //""__/"
L"""//__/"" "
EDITAR
Ahora que finalmente hay algunas otras respuestas publicadas, no me importa compartir una versión menos ofuscada:
let [|sx;sy|] = System.Console.ReadLine().Split([|'' ''|])
let x,y = int sx, int sy
let Line n start odd even =
printf "%s" start
for i in 1..n do
printf "%s" (if i%2=1 then odd else even)
printfn ""
// header
if x > 1 then
Line x " " " " " __ "
Line x " " "__" "/ //"
else
Line x " " "__" " "
// body
for i in 1..y-1 do
Line x "/" " //" "__/"
Line x "//" "__/" " //"
// footer
Line x "/" " //" "__/"
Line x "" "//__/" " "
Golfscript, 88 caracteres
Basado en la solución de mobrule . ¡Fue mucho trabajo conseguirlo más pequeño que ese! Las nuevas líneas son solo por claridad.
~:r;:c 3*):W 6/" __"*n
[][0]r[3 6]*+{[" ""__/ //"99*+>W<]+.},;
c 2%-1 1if:r%)[-1<]+r%
n*
Explicación:
~:r;,:c # read input into rows, columns
3 *):W # store c*3+1 into W
6 /" __"*n # write out " __" W/6 times, plus newline
[] # initialize output array
[0]r[3 6]*+ # create array [0] + [3,6] repeated r times
{ # for every entry in the input array...
[" ""__/ //"99*+ # create the magic string
>W< # truncate it between [n:W], where n is the cur entry
]+ # store this line in the output array
.},; # repeat for every entry in array
# now to handle the extra cases:
c 2%-1 1if:r% # reverse the array if c is odd, do nothing if it''s even
)[-1<] # take the last entry in the array, cut off the last char
+r% # put it back on the array, and un-reverse it
n* # now join the array with newlines
Aquí está mi entrada original en 118 caracteres :
Entrada tardía, ¡pero es la segunda más pequeña! (Estoy usando esto para aprender Golfscript). Las nuevas líneas son para mayor claridad.
~:r;:c 2%:o;c 2/:b" __"*n:e
{e" ""//"if"__/ //"b*o{"__"e{"":e}"/"if}{"":e}if n
"/"" //__/"b*o" //"""if n}r*
"//__/ "b o+*
C #, 216 caracteres
class B{static void Main(string[]a){int b=0,i=0,w=int.Parse(a[0])+1,z=2*w*(int.Parse(a[1])+1);for(;i<z;b=(i%w+i/w)%2)System.Console.Write("/// "[i>w&(w%2>0?i<z-1:i!=2*w-1)?b>0?0:1:2]+(++i%w<1?"/n":b>0?"__":" "));}}
Menos ofuscado
class B{
static void Main(string[]a){
int b=0,
i=0,
w=int.Parse(a[0])+1,
z=2*w*(int.Parse(a[1])+1);
for(;i<z;b=(i%w+i/w)%2)
System.Console.Write(
"/// "[i>w&(w%2>0?i<z-1:i!=2*w-1)?b>0?0:1:2]
+
(++i%w<1?"/n":b>0?"__":" ")
);
}
}
Usé el siguiente método:
input: 4 2
cols: 0 00 1 11 2 22 3 33 4 44
row 0:" | | |__| | | |__| |"
1:" |__|/| |/|__|/| |/|"
2:"/| |/|__|/| |/|__|/|"
3:"/|__|/| |/|__|/| |/|"
4:"/| |/|__|/| |/|__|/|"
5:"/|__|/| |/|__|/| | |"
- Itera de cero a (W + 1) * (H * 2 + 1). El * 2 es porque cada peine tiene 2 líneas de altura y +1 para representar la primera línea y el final de las líneas.
- Renderice dos "piezas" de un hexágono por iteración:
- Decida entre "", "/" y "/" para la primera parte
- Decida entre "__", "" y "/ n" para la segunda parte
El patrón es evidente si miras un panal lo suficientemente grande. La mitad de la lógica está allí solo para abordar las excepciones en la primera fila, el final de la segunda fila y la última celda.
C89 (136 caracteres)
x;y;w;main(h){for(h=scanf("%d%d",&w,&h)*h+2;y++
<h;++x)putchar(x>w*3-(y==(w&1?2:h))?x=-1,10:
"/ //__"[--y?y-1|x?(x+y*3)%6:1:x%6<4?1:5]);}
Lua, 227 caracteres
w,h,s=io.read("*n"),io.read("*n")*2+2," " for i=1,h do b=(i%2>0 and "/ //__" or "//__/ "):rep(w/2+1):sub(1,w*3+1) print(i==1 and b:gsub("[///]",s) or i==2 and b:gsub("^//",s):gsub("/$",s) or i==h and b:gsub("//$",s) or b) end
208 caracteres , cuando el ancho y el alto se leen desde la línea de comandos.
s,w,h=" ",... h=h*2+2 for i=1,h do b=(i%2>0 and "/ //__" or "//__/ "):rep(w/2+1):sub(1,w*3+1) print(i==1 and b:gsub("[///]",s) or i==2 and b:gsub("^//",s):gsub("/$",s) or i==h and b:gsub("//$",s) or b) end
NewLisp: 257 caracteres
Estoy seguro de que esta no es una solución óptima:
(silent(define(iv)(println)(set v(int(read-line))))(i''w)(i''h)(set''t(+(* 3 w)1))(set''l " __/ //__/ ")(define(pse(b 0))(println(slice(append(dup" "b)(dup(s 6 l)w))0 e)))(p 0 t)(p 4(- t(% w 2))1)(dotimes(n(- h 1))(p 6 t)(p 9 t))(p 6 t)(p 9(- t(%(+ w 1)2))))
Menos ofuscado
(silent
(define (i v)
(println)
(set v (int (read-line))))
(i ''w)
(i ''h)
(set ''t (+ (* 3 w) 1))
(set ''l " __/ //__/ ")
(define (p s e (b 0))
(println (slice (append (dup " " b) (dup (s 6 l) w)) 0 e)))
(p 0 t)
(p 4 (- t (% w 2)) 1)
(dotimes (n (- h 1))
(p 6 t)
(p 9 t))
(p 6 t)
(p 9 (- t(% (+ w 1)2))))
Estoy seguro de que podría escribir el ciclo de manera diferente y guardar dos líneas y algunos caracteres, por ejemplo, pero es tarde ...
Perl, 160 caracteres
$w=shift;for$h(-1..2*shift){push@a,join'''',((''/__'',''/ '')x($w+$h))[$h..$w+$h]}
$a[0]=~y#///# #;$a[1]=~s/./ /;s/_*$//for@a;$a[$w%2||$#a]=~s/. *$//;print$_,$/for@a
Ninguna astucia involucrada en absoluto: simplemente llene la matriz con personajes, luego elimine los que se vean feos.
La obra maestra de Strager tiene solo 137 caracteres cuando se le transporta a Perl, pero todo el crédito debe ir a él.
$w=shift;$/=$/;for$y(1..($h=2+2*shift)){print map+(split//,''_ /__/ '')
[$y-1?$y-2|$_?($_+$y%2*3)%6+2:1:$_%6<4],0..$w*3-!($w&1?$y-2:$y-$h)}
Perl, 99 caracteres
@P=map{$/.substr$".''__/ //'x99,$_,$W||=1+3*pop}0,(3,6)x pop;
chop$P[0-$W%2];print" __"x($W/6),@P
Última edición : se reemplazó un carácter guardado -($W%2)
con 0-$W%2
(gracias a A. Rex)
Explicación:
Para ancho W y altura H, la salida es 2 + 2 * H líneas largas y 3 * W + 1 caracteres de ancho, con mucha repetición en el medio de la salida.
Para mayor comodidad, dejamos que $W
sea 3 * W + 1, el ancho de la salida en caracteres.
La línea superior consiste en el patrón " __"
, repite W / 2 == $W/6
veces.
Las líneas pares incluyen el patrón repetitivo "/__/ "
, truncado a $W
caracteres. La segunda línea de salida es un caso especial, donde el primer carácter de la segunda línea debe ser un espacio en lugar de un /
.
Las líneas numeradas impares consisten en el patrón de repetición "/ /__"
, truncado a $W
caracteres.
Construimos una cadena: " " . "__/ /" x 99
" " . "__/ /" x 99
. Tenga en cuenta que el comienzo de esta cadena es el resultado deseado para la segunda línea. Esta línea que comienza en la posición 3 es la salida deseada para las líneas impares, y comienza en la posición 6 para las líneas pares.
El argumento LIST para la llamada al map
comienza con 0 y es seguido por H repeticiones de (3,6). La llamada al map
crea una lista de las subcadenas que comienzan en las posiciones apropiadas y son $W
= 3 * W + 1 caracteres de longitud.
Hay un ajuste más antes de imprimir los resultados. Si W es impar, entonces hay un carácter adicional en la segunda línea ( $P[0]
) que necesita ser cortado. Si W es par, entonces hay un carácter adicional en la línea inferior ( $P[-1]
) para cortar.
Python 2.6 - 144 caracteres incluyendo nuevas líneas
Puedo guardar unos 20 caracteres más si las entradas están separadas por comas.
C,R=map(int,raw_input().split())
print C/2*" __"+"/n "+("__/ //"*99)[:3*C-C%2]
r=0
exec''r+=3;print ("/__/ "*99)[r:r+3*C+1-r/6/R*~C%2];''*2*R
La versión que toma la entrada de la línea de comando es 4 bytes más:
import sys
C,R=map(int,sys.argv[1:])
print C/2*" __"+"/n "+("__/ //"*99)[:3*C-C%2]
r=0
exec''r+=3;print ("/__/ "*99)[r:r+3*C+1-r/6/R*~C%2];''*2*R
J , 143 caracteres
4(1!:2)~(10{a.)&,"1({.4 :0{:)".(1!:1)3
|:(18,(}:,32-+:@{:)3 3 8 1 1 10$~3*x){(,'' ''&(0})"1,'' ''&(0 1})"1)(,}."1)(}."1,}:"1)(3++:y)$"1''//',:'' _''
)
El uso de J se siente muy incómodo cuando se trata de cadenas de longitud variable y el tipo de interacción con el usuario orientada a la consola que se asume en otros idiomas. Aún así, creo que esto no es tan malo ...
Robando ideas una vez más (es mucho más fácil trabajar con J una vez que encuentras una forma de ver el problema de una manera estructurada), aquí está la obra maestra de mobrule portada en 124 (ick, es más larga que la original):
4(1!:2)~({.4 :0{:)".(1!:1)3
(x}~'' ''_1}(x=.-1-+:2|x){])((10{a.),('' '',,99#''__/ /',:'' __''){~(i.>:3*x)+])"0]595 0,3 6$~+:y
)
Ruby, 164
$ ruby -a -p bh.rb
La obra maestra de strager en Ruby ...
w,h = $F; w=w.to_i
(1..(h = h.to_i * 2 + 2)).each { |y|
(0...(w * 3 + (y != ((w & 1) != 0 ? 2 : h) ? 1:0))).each { |x|
$> << (''_ /__/ '' [
y - 1 != 0 ?
(y - 2 | x) != 0 ?
(x + y % 2 * 3) % 6 + 2 : 1 : (x % 6 < 4) ? 1:0]).chr
}
$> << $/
}
alias
w,h=$F;w=w.to_i
(1..(h=h.to_i*2+2)).each{|y|(0...(w*3+(y!=((w&1)!=0?2:h)?1:0))).each{|x|$><<(''_ /__/ ''[y-1!=0?(y-2|x)!=0?(x+y%2*3)%6+2:1:(x%6<4)?1:0]).chr}
$><<$/}
C # 377 caracteres
No quería decepcionar a nadie esperando la respuesta "divertida" de C #. Lamentablemente, no son 250 líneas ...;)
using System;
class P{
static void Main(string[] a){
int i,j,w=Int32.Parse(a[0]),h=Int32.Parse(a[1]);
string n="/n",e="",o=e,l="__",s=" ",r=s+s,b=@"/",f="/";
string[] t={r+r,l,b+l+f,r,l,f+r+b,e,f,b,s};
for(i=0;i<w;)o+=t[i++%2];
for(i=0;i<2*h;i++){
o+=n+(i%2==0?i!=0?b:s:e);
for(j=0;j<w;)
o+=t[((j+++i)%2)+4];
o+=i!=0?t[((w+i)%2)+6]:e;
}
o+=n;
for(i=0;i<w;)o+=t[i++%2+2];
Console.Write(o);
}
}
Groovy, # 375 caracteres
La misma lógica y código que @markt implementado en c #, pero han cambiado pocos lugares para Groovy :)
public class FunCode {
public static void main(a) {
int i,j,w=Integer.parseInt(a[0]),h=Integer.parseInt(a[1]);
String n="/n",e="",o=e,l="__",s=" ",r=s+s,b="//",f="/";
def t=[r+r,l,b+l+f,r,l,f+r+b,e,f,b,s];
for(i=0;i<w;)o+=t[i++%2];
for(i=0;i<2*h;i++){
o+=n+(i%2==0?i!=0?b:s:e);
for(j=0;j<w;)
o+=t[((j+++i)%2)+4];
o+=i!=0?t[((w+i)%2)+6]:e;
}
o+=n;
for(i=0;i<w;)o+=t[i++%2+2]; println(o);
}
}