Pythonのfractions.Fraction.__hash__が遅いっぽいという話
AtCoder Beginner Contest 168 E - ∙ (Bullet)を解いていたときに気づいた話です。
直角の関係になっているイワシを判定して組み合わせから引くという問題です。
直角の組み合わせは有理数ライブラリを使えば見つけやすいので、fractions.Fraction
を使って提出する。
……しかし、TLE
してしまいます。
その後自作の有理数ライブラリを作ってみて提出するとAC
になりました。
もともとfractionsが遅いことは有名だが、どうして大した計算もしていないのにTLE
になるのか?と疑問に思ったのでいろいろ試してみると、__hash__
関数が悪さしているんじゃないか?とたどり着きました。
Fraction
の__hash__
をオーバーライドして、__str__
をそのままハッシュ化することとしてみます。
class frac(Fraction): def __hash__(self): return hash(super().__str__())
提出すると、無事AC
できました。
__hash__
をオーバーライドするだけでは他の遅さが解決できるわけではないですが、dict
のキーとして参照する程度であればとりあえずやり過ごせますよという話でした。