呼ばれていないけど、私もコードゴルフしてみました2013年08月09日 03時06分

Code 2013 というイベントで出されたというコードゴルフのお題「JavaScript でデジタル時計」を見ているうちに、自分でもやりたくなったので挑戦してみました。

基本方針

出力が複数行にわたるなら 1 行ずつ処理していくのが素直な手ですが、このお題においてはそれだとひとつの文字に対する処理が細切れになってしまいます。

1 行ずつ処理していく場合のイメージ図

そこで、ある文字の出力処理をまとめてやってしまいましょう。行ごとにではなく列ごとに処理を進めていくのです。

1 列ずつ処理していく場合のイメージ図

20 分

方針が決まれば早速コーディング。以前、渋谷から 10 分のゴルフ場で似たようなお題「banner」に取り組んだときは三十六進数表記を使いましたが、とりあえずは読み書きしやすいよう二進数表記で進めます。

本番の制限時間は 20 分だったそうなので、こちらも 20 分で到達したところはこちら、

t = 0;
setInterval(function () {
    s = ' ■';
    p = [
        '111111000111111',
        '111110000000000',
        '111011010110111',
        '111111010110101',
        '111110010011100',
        '101111010111101',
        '101111010111111',
        '111111000010000',
        '111111010111111',
        '111111010111101',
        '000000101000000',
    ].map(function (b) { return parseInt(b, 2) });
    l = ['', '', '', '', ''];
    d = [
        t / 60 / 10 | 0,
        t / 60 % 10 | 0,
        10,
        t % 60 / 10 | 0,
        t % 60 % 10 | 0,
    ];
    for (i in d) {
        v = p[d[i]];
        for (j = 20; j--;) {
            l[j % 5] += s[v & 1];
            v >>= 1;
        }
    }
    document.body.innerHTML = l.join('<br>');
    t++;
}, 1000);

スペース・改行を取り除いて 458 バイト (UTF-8 でエンコードした場合) と、ちょっと詰めきれていません。二進数表記文字列 + map メソッドの組み合わせを十進整数リテラルに書き換えるだけで 284 バイトになるので、あと一歩ではあったのですが。

改良

このお題ではひとつの文字を表すのに、3 列 5 行、15 個の点を使っています。ひとつの文字に対するパターンが 15 ビットで表現可能ということは、JavaScript の 1 文字 (16 ビット) に収まるわけですね。

ほかにも、変数 sp はそれぞれ 1 箇所でしか使っていないので、変数を使わずリテラルを直接書くといった節約の成果がこれです。

t = 0;
setInterval(function () {
    l = ["", "", "", "", ""];
    for (i in d = [t / 600, t / 60 % 10, 10, t % 60 / 10, t++ % 10])
        /* "\u7E3F\u7C00\u76B7\u7EB5\u7C9C\u5EBD\u5EBF\u7E10\u7EBF\u7EBD\u0140" */
        for (v = "縿簀皷纵粜庽庿縐线纽ŀ".charCodeAt(d[i]), j = 20; j--; v >>= 1)
            l[j % 5] += " ■"[v & 1];
    document.body.innerHTML = l.join("<br>")
}, 1e3)

スペース・改行を取り除いて 230 バイトまで減らせました。さらに、setInterval の第 1 引数を関数ではなく文字列にすることで、220 バイトとなります。

上述の版では文書読み込み完了から 1 秒間が空いて時計の描画が始まります。サンプルと同じく文書読み込み完了と同時に時計が描画される、修正版 (229 バイト) を作りました。v >>= 1v /= 2 にするという変更も入れています。