Код Гольф: Улей
Соревнование
Самый короткий код по количеству символов, который сгенерирует улей из пользовательского ввода.
Улей определяется сеткой шестиугольников в размере, введенном пользователем как два положительных числа больше нуля (нет необходимости проверять ввод). Первый номер (W
) представляет ширину улья - или - сколько шестиугольников в каждом ряду. Второй номер (H
) представляет высоту улья - или - сколько шестиугольников на каждом столбце.
Одиночный шестиугольник состоит из трех символов ASCII: _
, /
а также \
и три строки:
__
/ \
\__/
Шестиугольники дополняют друг друга: первый столбец улья будет "низким", а второй будет высоким - чередующийся и повторяющийся по той же схеме, образуя W шестиугольников. Это будет повторяться H раз для формирования шестиугольников WxH.
Тестовые случаи:
Input:
1 1
Output:
__
/ \
\__/
Input:
4 2
Output:
__ __
__/ \__/ \
/ \__/ \__/
\__/ \__/ \
/ \__/ \__/
\__/ \__/
Input:
2 5
Output:
__
__/ \
/ \__/
\__/ \
/ \__/
\__/ \
/ \__/
\__/ \
/ \__/
\__/ \
/ \__/
\__/
Input:
11 3
Output:
__ __ __ __ __
__/ \__/ \__/ \__/ \__/ \__
/ \__/ \__/ \__/ \__/ \__/ \
\__/ \__/ \__/ \__/ \__/ \__/
/ \__/ \__/ \__/ \__/ \__/ \
\__/ \__/ \__/ \__/ \__/ \__/
/ \__/ \__/ \__/ \__/ \__/ \
\__/ \__/ \__/ \__/ \__/ \__/
Количество кодов включает в себя ввод / вывод (т.е. полную программу).
14 ответов
Perl, 99 символов
@P=map{$/.substr$".'__/ \\'x99,$_,$W||=1+3*pop}0,(3,6)x pop;
chop$P[0-$W%2];print" __"x($W/6),@P
Последнее редактирование: сохранена замена одного символа -($W%2)
с 0-$W%2
(спасибо А. Рекс)
Объяснение:
Для ширины W и высоты H вывод составляет 2+2 * H строк и 3 * W+1 символ в ширину, с большим количеством повторений в середине вывода.
Для удобства позвольте $W
быть 3 * W + 1, ширина вывода в символах.
Верхняя строка состоит из рисунка " __"
повторяется W/2 == $W/6
раз.
Четные строки состоят из повторяющегося узора "\__/ "
усеченный до $W
персонажи. Вторая строка вывода - это особый случай, когда первый символ второй строки должен быть пробелом вместо \
,
Нечетные линии состоят из повторяющегося шаблона "/ \__"
усеченный до $W
персонажи.
Мы строим строку: " " . "__/ \" x 99
, Обратите внимание, что начало этой строки является желаемым выводом для второй строки. Эта строка, начинающаяся с позиции 3, является желаемым выходом для нечетных строк и начинающейся с позиции 6 для четных строк.
Аргумент LIST для map
вызов начинается с 0 и сопровождается H повторениями (3,6). map
Вызов создает список подстрок, которые начинаются с соответствующих позиций и $W
= 3 * W + 1 символ длиной.
Перед печатью результатов необходимо выполнить еще одну настройку. Если W нечетное, то во второй строке есть дополнительный символ ($P[0]
) это должно быть chop
выкл. Если W четное, то в нижней строке есть дополнительный символ ($P[-1]
) рубить.
Python 2.6 - 144 символа, включая переводы строки
Я могу сохранить еще около 20 символов, если ввод разрешен через запятую.
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
Версия, принимающая данные из командной строки, составляет еще 4 байта:
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
C89 (136 символов)
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]);}
J, 143 символа
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'/\',:' _'
)
Использование J чувствует себя очень неловко, когда имеешь дело со строками переменной длины и своего рода консольно-ориентированным взаимодействием с пользователем, которое предполагается в других языках. Тем не менее, я думаю, это не так уж плохо...
Еще раз крадя идеи (с J гораздо легче работать, когда вы найдете способ взглянуть на проблему с помощью массива), вот шедевр mobrule, портированный на 124 (ик, он длиннее оригинала):
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
)
Perl, 160 символов
$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
Никакой сообразительности не требуется: просто заполните массив символами, а затем отсеивайте те, которые выглядят ужасно.
При переносе на Perl шедевр Страгера состоит всего из 137 символов, но вся заслуга должна быть у него.
$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)}
C#, 216 символов
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?"__":" "));}}
Менее запутанный:
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?"__":" ")
);
}
}
Я использовал следующий метод:
input: 4 2
cols: 0 00 1 11 2 22 3 33 4 44
row 0:" | | |__| | | |__| |"
1:" |__|/| |\|__|/| |\|"
2:"/| |\|__|/| |\|__|/|"
3:"\|__|/| |\|__|/| |\|"
4:"/| |\|__|/| |\|__|/|"
5:"\|__|/| |\|__|/| | |"
- Итерация от нуля до (W+1)*(H*2+1). Знак * 2 объясняется тем, что каждый гребень имеет высоту 2 строки и +1 для учета первой строки и конца строк.
- Рендеринг двух "кусочков" шестиугольника за итерацию:
- Выберите между " ", "\" и "/" для первой части
- Выберите между "__", " " и "\n" для второй части
Картина очевидна, если вы посмотрите на достаточно большие соты. Половина логики заключается только в устранении исключений в первом ряду, конце второго ряда и последней ячейке.
NewLisp: 257 символов
Я уверен, что это не оптимальное решение:
(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))))
Менее запутанный:
(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))))
Я уверен, что мог бы написать цикл иначе и сохранить, например, две строки и несколько символов, но уже поздно...
Руби, 164
$ ruby -a -p bh.rb
strager в Руби...
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
}
$> << $/
}
ака
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}
$><<$/}
Golfscript, 88 символов
Основано на решении mobrule. Было много работы, чтобы получить его меньше, чем тот! Новые строки только для ясности.
~:r;:c 3*):W 6/" __"*n
[][0]r[3 6]*+{[" ""__/ \\"99*+>W<]+.},;
c 2%-1 1if:r%)[-1<]+r%
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
Вот моя оригинальная запись на 118 символов:
Поздний вход, но он 2-й самый маленький! (Я просто использую их, чтобы выучить Golfscript). Новые строки для ясности.
~: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# 377 символов
Не хотел разочаровывать никого, ждущего "смешного" ответа C#. К сожалению, это не 250 строк, хотя...;)
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);
}
}
C89 - 261 необходимый символ
Все пробелы могут быть удалены. Мое решение использует вращение доски...
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));
}
Lua, 227 символов
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 символов, когда ширина и высота считываются из командной строки.
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
Groovy, № 375 символов
Та же логика и код, которые @markt реализовал в C#, но изменили несколько мест для 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);
}
}
F#, 303 символа
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"""\\__/"" "
РЕДАКТИРОВАТЬ
Теперь, когда наконец-то опубликованы другие ответы, я не против поделиться менее запутанной версией:
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 "" "\\__/" " "