Excel列名変換問題を解いてみた

11/4 23:10 不具合ありました。追記しています。


http://d.hatena.ne.jp/JunichiIto/20111102/1320253815
こちらの問題を解いてみた。
楽しそうなことやってるな、と羨ましくなったので。いい会社だと思う。

忘れたRubyを調べ直しながらどうにか1時間かけてここまで。問1だけで30分かかった。ほとんど忘れていてもどうにかなるRubyの易しさに感心した。

flg = ARGV[0];
arg = ARGV[1];

if (flg == "0")
    k = 0;
    sum = 0;
    arg.reverse.each_byte { |c|
        sum += ((c - 64) * (26 ** k));
        k += 1;
    }
    p sum;
elsif (flg == "1")
    a = arg.to_i;
    k = 0;
    while a > (26 ** k)
        k += 1;
    end
    k -= 1;
    
    sum = "";
    rest = a;
    while rest > 0
        i = rest / (26 ** k);
        rest -= i * (26 ** k);
        sum += (i + 64).chr;
        k -=1;
    end
    p sum;
end

書いてみて数字がアルファベットになっただけで、実はよくある問題だと気づいてリファクタリング。できたのは何度か書いた覚えがあるコードだった。

flg = ARGV[0];
arg = ARGV[1];

if (flg == "0")
    sum = 0;
    arg.each_byte { |c|
        sum = (sum * 26) + (c - 64);
    }
    p sum;
elsif (flg == "1")
    sum = "";
    rest = arg.to_i;
    while rest > 0
        i = rest % 26;
        sum = (i + 64).chr + sum;
        rest /= 26;
    end
    p sum;
end

この手の問題は解いた後になると、なぜあんなに時間がかかったのか理解できなくなるのが不思議。コードを書くところではなくロジックを考えているところに時間がかかっているということなのだろうか?

あと"A"から"Z"の中に数字の"0"に相当するものがないのに、どうしてこれが動くのかよく分かっていない。"Z"を"0"のように扱わなければならないのかと思い悩んだが、べつにそんな必要はないらしい。案ずるより産むが易しだった。ギリシャ数字も似たような感じなのだろうか。

そしてRubyPythonPerlも中途半端に手を出したきり放置してることを思い出して悲しくなった。

11/4 23:10 追記
すいません不具合ありました。上で懸念していたように、"Z"と"0"に関して特殊な処理が必要だったみたいです。テストのいい加減さが原因なので、ちゃんと自動テストしてれば気づいていたんだと思います。

flg = ARGV[0];
arg = ARGV[1];

if (flg == "0")
    sum = 0;
    arg.each_byte { |c|
        sum = (sum * 26) + (c - 64);
    }
    p sum;
elsif (flg == "1")
    sum = "";
    rest = arg.to_i;
    while rest > 0
        r = rest % 26;
        i = (r > 0) ? r : 26;
        sum = (i + 64).chr + sum;
        rest = (r > 0) ? (rest / 26) : (rest / 26 - 1);
    end
    p sum;
end