Code Golf:蜂巢

时间:2009-10-08 19:50:12

标签: language-agnostic code-golf rosetta-stone

挑战

按字符数排序的最短代码,它将根据用户输入生成蜂窝。

蜂窝被定义为由用户输入的大小六边形网格,作为两个大于零的正数(无需验证输入)。第一个数字(W)表示蜂箱的宽度 - 或 - 每行有多少个六边形。第二个数字(H)表示蜂箱的高度 - 或 - 每列上有多少个六边形。

单个六边形由三个ASCII字符组成:_/\,以及三行:

 __
/  \
\__/

六边形相互完成:蜂巢的第一列将为“低”,第二列将为高 - 交替并以相同的图案重复形成W六边形。这将重复H次以形成总共WxH六边形。

测试用例:

Input:
    1 1
Output:
     __
    /  \
    \__/

Input:
    4 2
Output:
        __    __
     __/  \__/  \
    /  \__/  \__/
    \__/  \__/  \
    /  \__/  \__/
    \__/  \__/

Input:
    2 5
Output:
        __ 
     __/  \
    /  \__/
    \__/  \
    /  \__/
    \__/  \
    /  \__/
    \__/  \
    /  \__/
    \__/  \
    /  \__/
    \__/

Input:
    11 3
Output:
        __    __    __    __    __
     __/  \__/  \__/  \__/  \__/  \__
    /  \__/  \__/  \__/  \__/  \__/  \
    \__/  \__/  \__/  \__/  \__/  \__/
    /  \__/  \__/  \__/  \__/  \__/  \
    \__/  \__/  \__/  \__/  \__/  \__/
    /  \__/  \__/  \__/  \__/  \__/  \
    \__/  \__/  \__/  \__/  \__/  \__/

代码计数包括输入/​​输出(即完整程序)。

14 个答案:

答案 0 :(得分:21)

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的字符(感谢A. Rex)

<强>解释

对于宽度W和高度H,输出为2 + 2 * H线长,3 * W + 1个字符宽,输出中间有很多重复。

为方便起见,我们让$W为3 * W + 1,输出的宽度为字符。

第一行包含模式" __",重复W / 2 == $W/6次。

偶数行包含重复模式"\__/ ",截断为$W个字符。第二行输出是一种特殊情况,第二行的第一个字符应该是空格而不是\

奇数行由重复模式"/ \__"组成,截断为$W个字符。

我们构造一个字符串:" " . "__/ \" x 99。请注意,此字符串的开头是第二行的所需输出。从第3位开始的这条线是奇数线的所需输出,从偶数位线的第6位开始。

map调用的LIST参数以0开头,后跟H重复(3,6)。 map调用会创建一个从适当位置开始的子字符串列表,$W = 3 * W + 1个字符长。

在打印结果之前还需要进行一项调整。如果W是奇数,则第二行($P[0])上有一个额外的字符,需要chop关闭。如果W是偶数,那么底线($P[-1])上会有一个额外的字符要切断。

答案 1 :(得分:10)

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

答案 2 :(得分:10)

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]);}

答案 3 :(得分:6)

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时,strager的杰作只有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)}

答案 4 :(得分:6)

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(ick,它比原来的更长):< / p>

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
)

答案 5 :(得分:5)

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:"\|__|/|  |\|__|/|  | |"
  1. 从零到(W + 1)*(H * 2 + 1)迭代。 * 2是因为每个梳子高2行,而+1代表第一行和行尾。
  2. 每次迭代渲染两个六边形的“碎片”:
  3. 第一部分“/”,“\”和“/”之间的决定
  4. 第二部分
  5. 决定“__”,“”和“\ n”

    如果你看一个足够大的蜂窝状,这种模式很明显。逻辑的一半只用于解决第一行,第二行结束和最后一个单元格中的异常。

答案 6 :(得分:4)

Ruby,164

$ ruby -a -p bh.rb

strager在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
  }
  $> << $/
}

又名

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}
$><<$/}

答案 7 :(得分:4)

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))))

我确信我可以用不同的方式编写循环并保存两行和几个字符,例如,但它已经晚了......

答案 8 :(得分:3)

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个字符的原始条目:

迟到,但它是第二小! (我只是用这些来学习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+*

答案 9 :(得分:2)

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));
}

答案 10 :(得分:2)

C#377 chars

不想让任何等待“搞笑”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);
    }
}

答案 11 :(得分:1)

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 ""    "\\__/"   "  "

答案 12 :(得分:1)

Groovy,#375 chars

相同的逻辑和@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);
        }
    }

答案 13 :(得分:1)

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