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 件のコメント:
コメントを投稿