Strategyパターンは、『アルゴリズム』を入れ替えるパターン。UMLの雰囲気なんかは目新しくないが、実用性は高そう。パーサとかスクレイピングとかね。
例ではStrategyがもろ『戦略』なんだけど、これが却って混乱させるというか。練習問題のソートのやつのほうが応用という意味では適していそう。
コード書いてて、自分でじゃんけんアルゴリズムを考えたくなるのは性なんでしょうかね。でも思いつかなかったので書いてないです。
何となく、囚人のジレンマに適用できるくらいまで抽象化してみようかと考えています。
ソースコード
strategy.py
# -*- coding: utf8 -*-
class __Strategy: #interface
def __init__(self): raise NotImplementedError
def nextHand(self): raise NotImplementedError
def study(self, win): raise NotImplementedError
import hand
import random as random1
class WinningStrategy(__Strategy):
def __init__(self, seed):
random1.seed(seed)
self.won = False
self.previousHand = None
def nextHand(self):
if not self.won:
self.previousHand = hand.getHand(random1.randint(0,2))
return self.previousHand
def study(self, win):
self.won = win
import random as random2
class ProbStrategy(__Strategy):
def __init__(self, seed):
random2.seed(seed)
self.history = [[1,1,1] for i in xrange(3)]
self.prevHandValue = 0
self.currentHandValue = 0
def nextHand(self):
def listConcat(listOfLists): return reduce(lambda a,b: a+b, listOfLists,[])
self.prevHandValue = self.currentHandValue
#ex. [3,2,5] -> [[0,0,0],[1,1],[2,2,2,2,2]] -> [0,0,0,1,1,2,2,2,2,2] -> choice one
self.currentHandValue = random2.choice(listConcat([[i for dummy in xrange(x)] for i,x in enumerate(self.history[self.currentHandValue])]))
return hand.getHand(self.currentHandValue)
def study(self, win):
if win:
self.history[self.prevHandValue][self.currentHandValue] += 1
else:
self.history[self.prevHandValue][(self.currentHandValue+1)%3] += 1
self.history[self.prevHandValue][(self.currentHandValue+2)%3] += 1
player.py
# -*- coding: utf8 -*-
class Player:
def __init__(self, name, strategy):
self.name = name
self.strategy = strategy
self.gamecount = self.wincount = self.losecount = 0
self.nextHand = strategy.nextHand
def win(self):
self.strategy.study(True)
self.wincount+=1
self.gamecount+=1
def lose(self):
self.strategy.study(False)
self.losecount+=1
self.gamecount+=1
def even(self):
self.gamecount+=1
def __str__(self):
return '[%s: %d games, %d win, %d lose]' % (self.name, self.gamecount, self.wincount, self.losecount,)
main.py
#!/usr/bin/env python
# -*- coding: utf8 -*-
from player import Player
from strategy import WinningStrategy, ProbStrategy
import sys
def main():
if not len(sys.argv) == 3:
print "Usage: python main.py randomseed1 randomseed2"
print "Example: python main.py 314 15"
sys.exit(0)
seeds = map(long, sys.argv[1:3])
player1 = Player("Taro", WinningStrategy(seeds[0]))
player2 = Player("Hana", ProbStrategy(seeds[1]))
for i in xrange(10000):
nextHand1 = player1.nextHand()
nextHand2 = player2.nextHand()
if nextHand1.isStrongerThan(nextHand2):
print "Winner:", player1
player1.win()
player2.lose()
elif nextHand2.isStrongerThan(nextHand1):
print "Winner:", player2
player1.lose()
player2.win()
else:
print "Even..."
player1.even()
player2.even()
print "Total result:"
print player1
print player2
if __name__=='__main__': main()
0 件のコメント:
コメントを投稿