31

チャレンジ

ユーザー入力からビーハイブを生成する、文字数別の最短コード。

蜂の巣は、ユーザーがゼロより大きい 2 つの正の数として入力したサイズの六角形のグリッドとして定義されます (入力を検証する必要はありません)。最初の数字 ( W) は、蜂の巣の幅、または各列にある六角形の数を表します。2 番目の数字 ( H) は、蜂の巣の高さ、または各列にある六角形の数を表します。

1 つの六角形は、3 つの ASCII 文字 ( _/および\、および 3 行)から作成されます。

 __
/  \
\__/

六角形は互いに補完します。蜂の巣の最初の列は「低く」なり、2 番目の列は高くなります - 同じパターンで交互に繰り返され、W 六角形を形成します。これを H 回繰り返して、合計 WxH の六角形を形成します。

テストケース:

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

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

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

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

コード カウントには、入力/出力 (つまり、完全なプログラム) が含まれます。

4

14 に答える 14

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

最後の編集: 1 文字を保存-($W%2)しました0-$W%2(thanks A. Rex)

説明:

幅 W と高さ H の場合、出力は長さ 2+2 * H 行、幅 3 * W+1 文字になり、出力の途中で多くの繰り返しが発生します。

便宜上、$W3 * W + 1 を文字単位の出力幅とします。

一番上の行はパターン" __"で構成され、W/2 ==$W/6回繰り返されます。

偶数行は、文字"\__/ "に切り捨てられた繰り返しパターンで構成され$Wます。出力の 2 行目は特殊なケースで、2 行目の最初の文字は ではなくスペースにする必要があります\

奇数行は、文字"/ \__"に切り捨てられた繰り返しパターンで構成され$Wます。

文字列を作成します: " " . "__/ \" x 99. この文字列の先頭は、2 行目の目的の出力であることに注意してください。位置 3 から始まるこの行は、奇数行の目的の出力であり、偶数番号の行では位置 6 から始まります。

呼び出しの LIST 引数mapは 0 で始まり、その後に (3,6) の H 回の繰り返しが続きます。このmap呼び出しは、適切な位置から始まる長さ$W= 3 * W + 1 文字の部分文字列のリストを作成します。

結果を印刷する前に、もう 1 つ調整する必要があります。W が奇数の場合、2 行目に追加の文字 ( $P[0]) を削除する必要がありますchop。W が偶数の場合、一番下の行 ( $P[-1]) に切り刻む余分な文字があります。

于 2009-10-09T03:15:47.240 に答える
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]);}
于 2009-10-08T22:14:08.030 に答える
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
于 2009-10-08T21:18:40.797 に答える
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

巧妙さはまったく関係ありません。配列に文字を入力してから、見栄えの悪いものを取り除くだけです。

strager の傑作は、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)}
于 2009-10-08T21:40:22.270 に答える
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 を使用する方がはるかに簡単です)、124 に移植された mobrule の傑作を次に示します (いや、オリジナルよりも長いです):

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
)
于 2009-10-09T02:09:37.217 に答える
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. 反復ごとに六角形の 2 つの「ピース」をレンダリングします。
  3. 最初の部分は「 」、「\」、「/」の間で決定します
  4. 2 番目の部分は「__」、「 」、「\n」のいずれかで決定します

十分な大きさのハニカムを見ると、パターンは明らかです。ロジックの半分は、最初の行、2 番目の行の終わり、および最後のセルの例外に対処するためだけに存在します。

于 2009-10-11T04:50:45.920 に答える
4

ルビー、164

$ ruby -a -p bh.rb

Ruby での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}
$><<$/}
于 2009-10-09T01:35:34.220 に答える
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 文字 の元のエントリです。

遅いエントリーですが、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+*
于 2010-06-10T16:10:15.490 に答える
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));
}
于 2009-10-08T21:32:19.613 に答える
1

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);
        }
    }
于 2009-10-12T09:16:14.030 に答える
1

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

于 2009-10-09T19:24:59.127 に答える
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 ""    "\\__/"   "  "
于 2009-10-08T20:59:19.383 に答える
1

ルア、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
于 2009-10-15T03:52:57.820 に答える