3の倍数と3が付く数字だけアホになり、5の倍数だけガルマっぽくなるスクリプトにチャレンジ

http://d.hatena.ne.jp/CortYuming/20080731/p1
…に触発されて、「3の倍数と3が付く数字だけアホになり、5の倍数だけガルマっぽくなるスクリプト」にチャレンジ。Python2.5専用。

#!coding: utf-8
#3の倍数と3が付く数字だけアホになり、5の倍数だけガルマっぽくなるスクリプト

DICT = [tmp.split(',') for tmp in [
    u',いち,に,さん,よん,ご,ろく,しち,はち,きゅう,じゅう',
    u',ぅい〜っち,ぬぅい〜,しゃぁ〜ん,しぃ〜,ごぉ,ろおぉ〜うく,すうぃ〜ち,ふはぁ〜ち,きゅぅ〜,じぃゅうぅ''']]
GARMA = [
   u'ぉ...この化け物がぁっ!落ちろ!落ちろぉぉっ!',
   u'ぅ...はかったな!シャアァ!!']

def int2strfmt(n, is_funny, garma_text):
    t = DICT[int(is_funny(n))]
    return ("%s"*4) % (
        t[(n/10)%10] if n >= 20 else '', t[10] if n >= 10 else '',
        t[n%10], garma_text(n))

print "\n".join([int2strfmt(n,
    lambda n: n % 3 == 0 or '3' in str(n),
    lambda n: GARMA[(n/5-1) % len(GARMA)]if n % 5 == 0 else '')\
    for n in range(1,40)] + [u'よん...ジオン公国に栄光あれぇぇっ!!'])

強い、しかし、普通に読めないw

まあ、普通の仕事で書くプログラムでまねしちゃだめな例だけど、部分部分で勉強になるコードになったのは成果でした。

  • 辞書を文字列のsplitで作成すると、gettextに優しいかも。
  • リスト内包のネストは複数行や1行にならない長い表現を一気に書ける。※
  • 「3の倍数と3が付く数字」を表す式が素敵。
  • ↑こういうのは、クライアントコードにラムダを書かせるといい。
  • %演算子で、文字列型への変換とフォーマットが同時にできる。
  • 40番目の出力はハードコード。決まりきっている事をアルゴリズムで出す必要はない。

※以下は等価なコード

s = []
for x in range(0,n):
  if x % 3 == 0:
    s.append(x * x)
s = map(lambda x: x * x, filter(lambda x: x % 3 == 0, range(0,n)))
s = [x * x for x in range(0,n) if x % 3 == 0]


Python的なるもの、とは、明示的に構造化された(行数増加を歓迎する)インデント構文だと思い込みがちだけど、そうじゃない側面でのPythonらしさを過剰演出して意識しようぜ。って感じ?

ちなみに、Python2.4以下だと、

if 条件 else 代替値

を、

  条件 andor 代替値

に置き換えてください。