美人サンタよりコードがお好き?JavaScriptエンジニアの変態プレイが炸裂(2/2 ページ)

» 2012年12月25日 10時45分 公開
[太田智美,@IT]
前のページへ 1|2       

ランキング上位5位のコード解説

 上位1位から5位までのコードと、柳井氏による解説付きコードは以下のとおり。

ランキング

1位:tompng氏(194文字)

2位:hogeover30氏(202文字)

3位:colun氏(210文字)

4位:mtym氏(214文字)

5位:hotpepsi氏(215文字)

6位:もけもけちきん氏(219文字)

7位:yvl氏(221文字)

8位:mbsp氏(227文字)

8位:sta_k氏(227文字)

9位:setchi_氏(228文字)

10位:OrgaChem氏(233文字)


 

1位:tompng氏のコード(194文字)
for(u=[i=4];i--;)for(x=y=s=j=c="";y<40;j++<160?c=(
p=1+r%78-x)*p+(q=1+r%38-y)*q<2?2-!p+!q:c:j=c&=s+="
\n|*-_%"[x++<80?c||2*Math.abs(x-41)<y+y%8|4:x&=u[y
++,i]=s])r=(i+j)*j*49999-5537&65535;return u
1位:柳井氏による解説付きコード
/*
 *  アニメの制御
 */
for(
    u=[i=4];    // 配列数と4要素の配列を初期化
    i--;        // 配列数分の処理を行い、iが0になれば終了
    )
    /*
     *  各マスとイルミネーションの制御
     */
    for(
        x=y=s=j=c="";   // 変数を初期化 0値の変数は""で初期化を統合
        y<40;           // 高さの回数計算
        j++<160     // 160はイルミネーションの個数
                    // 全てのイルミネーションの位置を確認
            ?
            /*
             *  イルミネーションの個数以下の場合は、現在XY位置に対応した
             *  イルミネーションが存在するか確認する
             */
            c=
                (
                    p=1+r%78-x  // 「1+r%78」はイルミネーションXの位置
                                // 「-x」することで、距離を求める
                )*p+(
                    q=1+r%38-y  // 「1+r%38」がイルミネーションYの位置
                                // 「-y」することで、距離を求める
                )*q
            <2      // イルミネーションの中心座標からの距離
                    // 距離が2未満ならばイルミネーションの一部が
                    // 現在走査中の座標に差し掛かっていると判断
                ?
                /*
                 *  イルミネーションの場所である
                 */
                    2-!p+!q 
                        // 中心か否かを判定 「!」を使うことで0か1を生成
                        // 中心なら2、上下なら1、左右なら3
                :
                /*
                 *  イルミネーションの場所ではない
                 */
                    c   // 初期値の0か、上記で判定した1〜3の値になる
            :
            /*
             *  イルミネーションを全て確認したら描画を行う
             */
            j=          // jを初期化(cと同じ値)
                c&=     // cを初期化(数値以外とビット演算して0を生成)
                s+=     // 文字列をアスキーアート1枚分連結していく
                "\n|*-_%"[
                    x++<80
                        ?
                            /*
                             *  通常の行位置
                             */
                            c   // イルミネーションであるなら、
                                // その位置の文字を取得
                            ||  // cが0だった(イルミネーションでない)
                                // 場合は以下を計算
                            2*Math.abs(x-41)    // 「2*Math.abs(x-41)」が
                                <       // 「y+y%8」より小さければ(trueなら)
                                y+y%8   // 「1」になる、falseなら0になる
                                    // 「y+y%8」で、以下のように増え、
                                    // 元の式と同じになる
                                    // 1+1=2, 2+2=4, 3+3=6, ... 7+7=14,
                                    // 8+0=8, 9+1=10, 10+2=12, ...
                                |4  // 0|4で 0|b100なのでb100 つまり4→「_」
                                    // 1|4で 1|b100なのでb101 つまり5→「%」
                        :
                            /*
                             *  改行位置
                             */
                            x&=     // xを初期化(数値以外とビット演算して0化)
                                u[
                                    y++,    // 行を1行加算
                                    i       // uの配列の現在位置iに対して
                                ]=s         // 連結し続けているsを格納
                    ]
    )   // 内側のfor文の「)」
        r=(i+j)*j*49999-5537&65535;     // 乱数もどき
            // 0xFFFF = 65535
            // 59999-(0x10000)=-5537
            // →「+59999 & 0xFFFF」と「-5537 & 0xFFFF」は等価
            // 例)0xF = 15 = b1111
            // 9 の場合は 9+(0x10) = 9+16 = 25
            // 9 の場合は 9-(0x10) = 9-16 = -7
            // 10+ 25 & 15 → 35 & 15 →b100011 & b1111 → b11
            // 10+  9 & 15 → 19 & 15 → b10011 & b1111 → b11
            // 10-  7 & 15 →  3 & 15 →    b11 & b1111 → b11
            // マスクする値+1を足したり引いたりした値でも
            // 同じ結果になる
return u
2位:hogeover30氏のコード(202文字)
for(r=[a=4];a--;)for(p=y=r[a]="";y<40;p-=y%8?-1:3)
for(x=!y++;x<81;r[a]+="_%*|-\n"[x++?f:5])for(i=f=4
1-p<x&x<p+41;i<160;f=(q=2*d*d+c*c)>2?f:q+2)t=(a+i)
*i++*49999-5537&65535,c=t%38+2-y,d=t%78+2-x;return
 r
2位:柳井氏による解説付きコード
/*
 *  アニメの制御
 */
for(
    r=[a=4];    // 配列数と4要素の配列を初期化
    a--;        // 配列数分の処理を行い、aが0になれば終了
    )
    /*
     *  y軸の制御
     */
    for(
        p=y=r[a]="";    // 変数を初期化 0値の変数は""で初期化を統合
        y<40;           // 高さの回数計算
        p-=y%8?-1:3     // 「y%8」が0(false)になる時は、木のジグザグ
                        // が発生する場所なので「3」を引く。
                        // 通常の場合は、1段y軸が下がるごとに1ずつ
                        // 木のすそ野の幅を広くしていく
        )
        /*
         *  x軸の制御
         */
        for(
            x=!y++;     // 最初の1回目のみ、xをtrue(1)で初期化
                        // 2回目からは、xをfalse(0)で初期化
                        // 2回目の0から、文字列の改行を参照する
                        // ようになる
            x<81;       // 横幅の回数計算
            r[a]+="_%*|-\n"[x++?f:5]    // xが0の場合は改行
                                        // その他の場合は
                                        // アスキーアートを描画
            )
            /*
             *  イルミネーションと背景と木
             */
            for(
                i=f=
                    41-p<x&x<p+41;
                    // 背景なのか木なのかを判定
                    // 背景なら0(_)、木なら1(%)の文字列を参照
                    // 文字の位置を参照するfには0か1が入る
                    // この値と同じ値を使い、イルミネーションの
                    // ループを回すiを初期化する
                    // 「i = 1」なら、ループの開始位置0にならない
                    // のではという問題は、iが0の場合は一意に
                    // x=18,y=36となり、ここは背景の位置なので
                    // 「i = 0」の判定を行う必要がない。
                    // なので、「i = 0」を飛ばして、「i = 1」から
                    // 開始して構わない
                i<160;      // イルミネーションの数だけ確認
                f=(q=2*d*d+c*c)>2?f:q+2
                    // イルミネーションの中心座標からの距離が2超なら
                    // f(以前に入った値と同じ値)を取る
                    // 2未満ならqを取る(新たな値になる)
                    // 0は中心、1は縦線(c*c)、2は横線(2*d*d)
                    // この0〜2に2を足すことで、文字列「"_%*|-\n"」の
                    // 「*|-」を取得することができる
                )
                t=(a+i)*i++*49999-5537&65535,   // 乱数もどき
                                // iの値を利用した後1増やす
                    // 0xFFFF = 65535
                    // 59999-(0x10000)=-5537
                    // →「+59999 & 0xFFFF」と「-5537 & 0xFFFF」は等価
                    // 例)0xF = 15 = b1111
                    // 9 の場合は 9+(0x10) = 9+16 = 25
                    // 9 の場合は 9-(0x10) = 9-16 = -7
                    // 10+ 25 & 15 → 35 & 15 →b100011 & b1111 → b11
                    // 10+  9 & 15 → 19 & 15 → b10011 & b1111 → b11
                    // 10-  7 & 15 →  3 & 15 →    b11 & b1111 → b11
                    // マスクする値+1を足したり引いたりした値でも
                    // 同じ結果になる
                c=t%38+2-y,     // 「(t%38+1)-(y-1)」
                d=t%78+2-x;     // 「(t%78+1)-(x-1)」
                                // 距離を取る。1を引いているのは
                                // x, y は1で開始しているから
return r
3位:colun氏のコード(210文字)
for(v=u=[a=w=x=81];~a;x+160?0<x--?v[x]="_%\n"[2*!z
|Math.abs(z-82)<y+y%8]:v[y=b%78+b%38*w+w]=v[v[++y]
="*",v[y-w]=v[y+w]="|",y+1]="-":u[a--]=v.join(v=[]
,x=3239))y=x/w|0,z=x%w*2,b=(x-a)*x*49999-5537&6553
5;return u
3位:柳井氏による解説付きコード
/*
 *  全ての計算を1つのループで回す
 */
for(
    v=u=[a=w=x=81]; // v, u を配列として初期化
                    // (中の値には意味がない)
                    // a, w, x を81で初期化
    ~a;     // 「~」は、4バイト整数と見なして
            // 各ビットを反転させた結果を返す
            // 例)
            // 81 → -82 → true
            //  1 →  -2 → true
            //  0 →  -1 → true
            // -1 →   0 → false
            // -2 →   1 → true
            // つまり a が-1になるまで計算を行う
    x+160   // イルミネーション計算の分、160下駄を履かせる
    ?
        /*
         *  アスキーアートの描画行う
         */
        0<x--       // x を減算
        ?
            /*
             *  x が0より大きい間は背景と木と改行の判定
             */
            v[x]="_%\n"[
                2*!z    // z が0の場合(改行位置)のみ「!z」は
                        // true(1)になる
                        // そのため、で2番目の文字「\n」を
                        // 参照する
                        // その他の場合は「!z」はfalse(0)
                        // になる
                        // そのため「2*0=0」で「|」以降に
                        // 1が来なければ「_」を参照する
                    |
                    Math.abs(z-82)<y+y%8
                        // z は2刻みで0〜160を取る
                        // 「Math.abs(z-82)」で真ん中から
                        // 折り返す
                        // 「y+y%8」で、以下のように増え、
                        // 元の式と同じになる
                        // 1+1=2, 2+2=4, 3+3=6, ... 7+7=14,
                        // 8+0=8, 9+1=10, 10+2=12, ...
                ]
        :
            /*
             *  x が0より小さい場合はイルミネーションの判定
             *  (ここで160の下駄を履かせたのが生きてくる)
             */
            v[
                y=b%78+b%38*w+w         // イルミネーション
                                        // の位置を計算
            ]=                          // 横棒が入る
                v[                      // 横棒が入る
                    v[++y]="*",         // 中心が入る
                    v[y-w]=v[y+w]="|",  // 縦棒が入る
                    y+1
                ]=
                    "-"
    :
        /*
         *  文字列を結合して配列に格納
         */
        u[a--]=v.join(v=[],x=3239)
            // join([])で、空文字連結と同じ
            // joinの第2引数(使わない場所)を利用して
            // 「x=3239」をセット
            // 3239 = (横80字+改行1字)×40行−末尾改行1字
            // 「u[a--]」配列4つではなく、a=81で設定された
            // 数のアスキー後が格納される
    )
    /*
     *  描画に必要な値を計算
     */
    y=x/w|0,    // y 座標の値
                // x/w の浮動小数点数に対してOR演算で0を
                // 指定することで、浮動小数点数を整数と
                // みなして計算を行い、結果的に整数を作る
    z=x%w*2,    // z は2刻みで0〜160を取る
    b=(x-a)*x*49999-5537&65535; // 乱数もどき
        // x がマイナスの間だけ、イルミネーション用の
        // 変数として使われる。元のコードは「(a+i)*i」
        // で正の値を前提としたコード
        // このiの位置にマイナスであるxを入れると値が
        // おかしくなる
        // そこで「(-a+x<負値>)*x<負値>」として、同等の
        // 計算が行えるようにする
        //
        // 0xFFFF = 65535
        // 59999-(0x10000)=-5537
        // →「+59999 & 0xFFFF」と「-5537 & 0xFFFF」は等価
        // 例)0xF = 15 = b1111
        // 9 の場合は 9+(0x10) = 9+16 = 25
        // 9 の場合は 9-(0x10) = 9-16 = -7
        // 10+ 25 & 15 → 35 & 15 →b100011 & b1111 → b11
        // 10+  9 & 15 → 19 & 15 → b10011 & b1111 → b11
        // 10-  7 & 15 →  3 & 15 →    b11 & b1111 → b11
        // マスクする値+1を足したり引いたりした値でも
        // 同じ結果になる
return u
4位:mtym氏のコード(214文字)
for(i=r=[4];i--;)for(p=[w=y=x=40],h=t=0;y;p[h++]='
_%\n'[x+w?x--<t&~x<t:(t+=--y%8?1:-3,x=w,2)])for(r[
i]=p.join(c='');c<160;)for(n=5,f=(i+c)*c++*49999-5
537&65535,o=f%78+f%38*81;n--;p[o+=n%3?1:80]='|-*-|
'[n]);return r
4位:柳井氏による解説付きコード
for(
    i=r=[4];    // 戻り値の配列rを初期化
                // iは要素数1の配列
                // 要素数1の数値配列は数値計算を行うと
                // 数値変数として動作する(要素数2以上
                // ではNaN(Not a Number)になる)
                // 同様の処理は文字列でも行える
    i--;        // 戻り値用の配列4つ分を計算
    )
    for(
        p=[w=y=x=40],   // pは配列として初期化
                        // w, y, x は40で初期化
                        // ※ y は座標位置ではなく行数分
                        //    処理をするカウンタでしかない
        h=t=0;          // h, t は0で初期化
        y;              // y が0になったら(全行走査
                        // したら終了)
        p[h++]='_%\n'[  // h で文字位置を指定
            x+w         // 「x+40」とすることで
                        // アスキーアートを
                        // 0になるまで80回描画可能
            ?
                x--<t&~x<t
                        // 「(x--<t)&(~x<t)」
                        // 左辺は x の値がt以下
                        // 右辺は x-1 の反転なので
                        // 元の x の -x に等しい
                        // なので 右辺は -x の値がt以下
                        // 満たすなら1で「%」を参照
                        // 満たさないなら0で「_」を参照
            :
                // 改行位置
                (
                    t+=--y%8?1:-3,  // 改行位置なのでyを減算
                        // 「y%8」が0(false)になる時は、木のジグザグ
                        // が発生する場所なので変化量は-3
                        // 通常の場合は、1段y軸が変化するごとに
                        // 変化量は1
                        // その値をtに加える
                    x=w,            // xを40に戻す
                    2               // 文字列の改行位置を参照
                )
        ]
        )
            for(
                // ここで、戻り値用の配列に結合した文字列を入れる
                r[i]=p.join(c='');  // c を''で初期化し0とみなす
                                    // joinは''の空文字列で結合
                c<160;              // イルミネーションの計算
                )
                for(
                    n=5,    // イルミネーションの文字数5
                    f=(i+c)*c++*49999-5537&65535,
                    // 0xFFFF = 65535
                    // 59999-(0x10000)=-5537
                    // →「+59999 & 0xFFFF」と「-5537 & 0xFFFF」は等価
                    // 例)0xF = 15 = b1111
                    // 9 の場合は 9+(0x10) = 9+16 = 25
                    // 9 の場合は 9-(0x10) = 9-16 = -7
                    // 10+ 25 & 15 → 35 & 15 →b100011 & b1111 → b11
                    // 10+  9 & 15 → 19 & 15 → b10011 & b1111 → b11
                    // 10-  7 & 15 →  3 & 15 →    b11 & b1111 → b11
                    // マスクする値+1を足したり引いたりした値でも
                    // 同じ結果になる
                    o=f%78+f%38*81;     // 中心の左上を基準点に
                    n--;                // nが0になるまで実行
                    p[
                        o+=n%3?1:80
                            // 改行があるので横81文字
                            // なので、80をy軸の移動量に取ると
                            // 斜めに移動することになる
                            // そのため、星の上部(@の位置)から
                            // 移動を開始して、右(1)、下(80)、
                            // 右(1)、右(1)、右(1)、下(80)と
                            // 移動する
                            // @|
                            //  -*-
                            //    |
                    ]=
                        '|-*-|'[n]      // nで取得位置を指定
                    );
return r
5位:hotpepsi氏のコード(215文字)
for(a=c=k=y=t=z='',b=[],i=h=40;j=y%8+y>>1,r=(a+k)*
k*49999-5537&65535,v=r%38-y+1,w=r%78-h+i+1,a<4;)h+
i?k++<160?z=v*v+w*w<2?v?4:w?2:6:z:(c+="_%--||**"[z
|i*i--<j*j],k=z=0):(i=h,++y<h?c+='\n':(b[a++]=c,c=
y=''));return b
5位:柳井氏による解説付きコード
for(
    a=c=k=y=t=z='',     // 変数を初期化
    b=[],               // 戻り値用の配列を初期化
    i=h=40;             // 40で初期化
    j=y%8+y>>1,         // 「y>>1」で整数演算の「÷2」と同じ
                        // 「y+y%8」で、以下のように増え、
                        // 元の式と同じになる
                        // 1+1=2, 2+2=4, 3+3=6, ... 7+7=14,
                        // 8+0=8, 9+1=10, 10+2=12, ...
    r=(a+k)*k*49999-5537&65535,     // 乱数もどき
        // 0xFFFF = 65535
        // 59999-(0x10000)=-5537
        // →「+59999 & 0xFFFF」と「-5537 & 0xFFFF」は等価
        // 例)0xF = 15 = b1111
        // 9 の場合は 9+(0x10) = 9+16 = 25
        // 9 の場合は 9-(0x10) = 9-16 = -7
        // 10+ 25 & 15 → 35 & 15 →b100011 & b1111 → b11
        // 10+  9 & 15 → 19 & 15 → b10011 & b1111 → b11
        // 10-  7 & 15 →  3 & 15 →    b11 & b1111 → b11
        // マスクする値+1を足したり引いたりした値でも
        // 同じ結果になる
    v=r%38-y+1,     // 「r%38+1」から y を引いて中心からの距離
    w=r%78-h+i+1,   // 「r%78+1」から「h-i」(40-i)(iは40から始
                    // まるので、0, 1, 2...と推移)を引いて
                    // 中心からの距離
    a<4;    // aが4未満まで(配列数だけ)ループを回す
    )
    h+i     // h は固定値40、i は40から開始され減算されていく
            // そのため「40+i」が0になるまでがアスキーアートで
            // 0で改行と、戻り値用配列の遷移
    ?
        /*
         *  アスキーアートの処理
         */
        k++<160     // イルミネーションを調べる
        ?
            /*
             *  イルミネーションの判定
             */
            z=
                v*v+w*w<2   // 中心からの距離が2未満
                ?
                    /*
                     *  イルミネーションが存在
                     */
                    v   // 縦方向の確認
                    ?
                        4   // 0でない「|」である
                    :
                        w   // 横方向の確認
                        ?
                            2   // 0でない「-」である
                        :
                            6   // v, w 共に0なので「*」
                :
                    /*
                     *  イルミネーションでないので
                     *  直前の z の値をそのまま維持する
                     */
                    z
        :
            /*
             *  文字列を参照して結合
             */
            (
                c+="_%--||**"[
                    z   // イルミネーションの文字列参照位置
                        // 値は2(b10)、4(b100)、6(b110)
                        // なので、下の式で1が来た場合には
                        // 参照位置が1つ右にずれる
                        // なので「--||**」と2文字ずつある
                    |
                    i*i--<j*j   // 中心位置からの距離の比較
                        // i は0を中心に対称に広がる2乗で
                        // 負の符号を相殺して、jの2乗と比較
                        // 距離がjの範囲内なら1、外なら0
                ],
                k=z=0   // イルミネーション系変数を初期化
                        // k カウント
                        // z 文字列参照位置
            )
    :
        /*
         *  アスキーアート以外の処理
         */
        (
            i=h,    // 横ライン移動用のiを40で初期化
            ++y<h   // yが40行以内か確認
            ?
                c+='\n' // 40行以内なので改行を追加
            :
                (
                    b[a++]=c,   // 文字列を配列に格納し
                                // 対象配列を次に移行
                    c=y=''      // c を空文字で初期化
                                // y を空文字(0)で初期化
                )
        );
return b


前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。