Google Code Jam で得た Python の tips(3)

目次

Part1
Part2
  • リスト
Part3(この記事)
  • 数学
  • ビット演算
  • 条件式
  • ループ
  • 例外処理
  • その他
  • おまけ:今回のテンプレート

数学

絶対値

abs() は math モジュール必要なし。
float を扱える fabs() は要mathモジュール。

最大公約数
from fractions import gcd
gcd(a,b)


python2.6以降でのみ使える。

出典:404 Not Found

math.asin に 1より大きい値を与えると

ValueError が返ってくる。

ValueError: math domain error
基数変換

int(str,base) で変換する。

print int("100",2)


4 が返ってくる。

乱数生成

random モジュールを使う。

import random
print random.randint(10,100)


これで 10<=x<=100 の値が返ってくる。
rand.seed() としなくてもシステムクロックで初期化される。

ビット演算

XOR
a ^ b


そのまんま。

右シフト
N = 16
N >>= 1


これで 8 になる。

条件式

条件式の並列にリストを使う

以下の式は等価。上の方が簡潔で見やすい。

if 0 in [x%2, x%3, x%5, x%7]:
if x%2 == 0 or x%3 == 0 or x%5 == 0 or x%7 == 0:


出典:GCJ2008 1C-B Klinck

for-else や while-else

公式チュートリアルより引用。実行例はリンク先を参照のこと。

ループ文は else 節を持つことができます; else 節は、 (for で) 反復処理対象のリストを使い切ってループが終了したとき、 または (while で) 条件が偽になったときに実行されますが、 break 文でループが終了したときは実行されません。


出典:404 Not Found

return 文における条件分岐
return A if condition else B


とすると、condition が true なら A が、false なら Bが返される。

ループ

xrange

range はシーケンスを丸ごとメモリにロードするので巨大なループをすると危険。
xrange を使うこと。
ただし、python3 では xrange が廃止され、range が従来の xrange のような振る舞いをするので逆に xrange は使ってはいけない、というか使えない。

出典:404 Not Found

rangeを逆向きに走らせる
range(bigger,smaller,-1)
yield

GCJ 2009 1A-A kinaba の解法が鮮やか過ぎる。
そして非常に実行時間が短い。

例外処理

as は python2.6 以降

python2.5 以下で実行するとエラーになる。

try:
    some code
except Error as e:
    some code


逆にカンマは python2.6 まで。python3 以降はエラーになる(はず)

try:
    some code
except Error,e:
    some code
assert 文

以下の式は等価。

assert i == 0
if __debug__:
    if not i == 0: raise AssertionError


__debug__ はデフォルト True で、-O オプション(最適化オーオプション) つきのときは False。

C++ の話になるが、GCJ 2008 1B-C bmerry は assert を組み込んでおくことで、実際の出力に影響を与えることなく、期待しない値が出てきたときに例外を吐くように実装していた。

出典:6.2 Assert 文 (assert statement)

その他

__main__
if __name__=="__main__":
    main()


これで、このファイルが実行されたときのみ if 内の動作をさせることができる。

出典:26.3 __main__ -- トップレベルのスクリプト環境

python プロファイラ

python -m profile で起動できる。

future 文

これを使えば標準化されていない、将来のバージョンに搭載される予定のモジュールを使えるようになる。

実行時間の計測
import time
t0 = time.clock()
# (中略)
print t0 - time.clock()


これをテストケースごとに実行することで実行時間を計測できる。

出典:GCJ2009 1B-C vlad

おまけ:今回のテンプレート


zibada さんのコードをベースに、こんな感じでテンプレート作りました。

import sys
import time
import psyco
psyco.full()
def dbg(a): sys.stderr.write(str(a) + "\n")
def readint(): return int(raw_input())
def readfloat(): return float(raw_input())
def readarray(f): return map(f,raw_input().split())
def alloc(size, default = 0): return [default] * size

t00 = time.clock()

def solve():
    return 0

for t in xrange(readint()):
    t0 = time.clock()
    dbg("Test #%d:" % (t+1))
    ans = solve()
    print "Case #%d: %d" % (t+1,ans)
    dbg("time %.2f sec" % (time.clock() - t0))

dbg("total time %.2f sec" % (time.clock() - t00))


Part1 / Part2 / Part3