LL Golf Hole 7 - バイト数を読みやすくする

LL Golf Hole 7 にて LL Golf Hole 7 - バイト数を読みやすくするというお題で出題されていますので、これを解いていきます。

しかし、この設問ですが、「詳しくはサンプルのコードを参考にしてください」と書かれてあり、それが Ruby と思われるのですが、何も説明がないのはどうなんでしょう? Ruby が読めないと解けない設問というのは良くないと思います。

要約すると、「1 以上のバイト数を示す整数に対し、2進接頭辞で示される SI 接頭辞を付けたものに変換しなさい」というものです。 コードを読んでも分かるように、1024 ではなく 1000 で割れということのようです。 かなり行間を読まなければ分かりません。

解法ですが、与えられた整数を 1000 づつで割って、余りが 1000 を切ったら、余りの数字に単位を付けることで得られます。

#! /usr/bin/gawk -f
# byte_readable.awk

BEGIN {
    split("kMGTPEZY", unit, "");
    base = 1000;
}

{
    num = $0;
    while (num > base) {
        num = num / base;
        i++;
    }
    print num unit[i];
}

さて、実行してみます。

$ echo 10000 | gawk -f byte_readable.awk
10k
$ echo 10000000 | gawk -f byte_readable.awk
10M

正しく実行されているようです。

さて、ここで少しだけゴルフを行ってみます。

$ echo 10000 | gawk 'split("kMGTPEZY",u,""){for(;$0>999;i++)$0/=1000}$0=$0u[i]'
10k

こんな感じでしょうか?

  • BEGIN はそれだけで 5 + 2 文字を消費するので使わずに、パターン (式) として split() 関数を用いて常に真になるようにしてあります。
  • アクションでは for ループのみです。
  • 再度、パターンで $0 に解を代入することで、自動的に print $0 を行っています。

ゴルフの楽しさ

なぜゴルフって成立するのでしょうか。 それは、皆が同じ入力を受け取り、同じアウトプットを出力する (一字一句も違ってはいけない) という決められた枠の中でプレーするからです。 しかも、通常は与えられた言語の与えられたバージョンを使います。 OS のバージョンの違いや Sucks に翻弄されてしまいますが、これをクリアできるのは本当に知り尽くしたものだけです。 もちろん、こうしたことは Code Golf でも anarchy golf でも共通しています。 だから楽しいし、苦労するし盛り上がるわけです。 インプットが曖昧、アウトプットは他人に合わせるのはゴルフと言わない気がしますが、どうなんでしょうか?

なんでそうなるのか?

ゴルフは時として数バイトを理解するのに数時間頭を悩ましてくれますが、gawk には便利なプロファイル機能があります。 これは gawk の代わりに pgawk として実行することで、カレントディレクトリに awkprof.out というファイルができます。 今回のゴルフでは以下のようなものになります。

    # gawk プロファイル、作成日時 Mon Aug 25 23:57:11 2008
    # ルール
     1  split("kMGTPEZY", u, "")    { # 1
     1      a = $0
     1      for (; a > 999; i++) {
     1          a /= 1000
        }
    }
     1  a = au[i]    {
        print $0
    }

複雑なプログラムを理解するのにも大いに役に立ってくれることでしょう。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png