はじめに
トランプカードをそのカードの数字順にソートしたり、最大または最小の数字を取得したりするうえで、演算子のオーバロードとの関係が気になったので調べてみた。
前提事実及び要件
トランプのカード52枚のそれぞれには、A(エース)からK(キング)までのいずれかの数字(乃至、数字と1対1対応する文字)と、スペード('S')、ハート('H')、ダイヤ('D')、クラブ('C')との組みが印字されている。
ここで、複数のカードがプレイヤーの手に配られることを想定する。この複数のカードを小さい順から数字順に並べ変えたい。なお、Aは14に相当し、Jは11に相当し、Qは12に相当し、Kは13に相当し、その他の数字はその数字に相当する値として評価される。また、処理の都合上、10をTの文字で置き換えている。
たとえば、スペードのエース(A,S), ダイヤの2(2,D), クラブのジャック(J,C), ハートの8(8,H), ダイヤの8(8,D)といったカードが配られた場合に、ダイヤの2(2,D), ハートの8(8,H), ダイヤの8(8,D) , クラブのジャック(J,C), スペードのエース(A,S)のように並べ替えたい。(数字が同じの8については順不同)
また、これらの数字の組みから最大の数字を有するカード、すなわちスペードのエースを抜き出したい。
今回実験したこと
上記前提のもと、演算子のオーバロードで、sort()やらsorted()やらmax()やらmin()やらがどのように動くのかということを実験してみた。
その1 Cardクラスの作成
数字とマークとをインスタンス変数として持ち、そのうち数字によって大きさを決めるCardクラスを定義してみた。
class Card:
Numbers = {'A':14,'T':10,'J':11,'Q':12,'K':13}
def __init__(self, number, mark):
if number in self.Numbers:
self.number = self.Numbers[number]
else:
self.number = int(number)
self.mark = mark
def __cmp__(self,other):
if self.number > other.number:
return 1
elif self.number < other.number:
return -1
else:
return 0
このクラスを使った演算子に関する実行結果は次のとおり。
>>> c1 = Card('A','S')
>>> c2 = Card('2','D')
>>> print c1 > c2
True
>>> c3 = Card('J','C')
>>> print c2 > c3
False
>>> c4 = Card('8','H')
>>> c5 = Card('8','D')
>>> print c4 == c5
True
次はsort()を試してみたところ、きちんとソートされたっぽい。
>>> hand = [c1, c2, c3, c4, c5]
>>> hand.sort()
>>> print hand[0].number, hand[0].mark
2, 'D'
>>> print hand[4].number, hand[4].mark
14, 'S'
sorted()でも変わらず。
>>> hand = [c1, c2, c3, c4, c5]
>>> print sorted(hand)[0].number
2
次はmax(),min()を使ってみた。
>>> hand = [c1, c2, c3, c4, c5]
>>> print max(hand).number
14
>>> print min(hand).number
2
どうやら演算子のオーバロード(より正確にはその基礎となる__cmp__
のオーバロード)で演算子だけでなく、sort, sorted, max, minなども正常に動くようである。多分に、sum()なども動くのではないだろうか。下手をするとmathの階乗関数なども動きそうな気もする。