# -*- coding: utf-8 -*- from saichugenlib import * def get_2_cards(cards): "given cards, return (card1, card2)" for o1 in cards: for o2 in cards: if o1 == o2: continue yield (o1, o2) def get_2_cards_with_rest(cards): "given cards, return (card1, card2, rest)" for o1 in cards: for o2 in cards: if o1 == o2: continue rest = cards[:] rest.remove(o1) rest.remove(o2) yield (o1, o2, rest) def think_a_turn(unknowns, hand, measure): "1ターンでの最善手探索 measureが良さを返す関数" max_score = -1 max_hand = None for my in hand: score = 0 for o1 in unknowns: for o2 in unknowns: if o1 == o2: continue score += measure(my, o1, o2) # print my, score if score > max_score: max_score = score max_hand = my return (max_score / float(len(unknowns) * (len(unknowns) - 1)), max_hand) def end_of_turn(play, round_score): "ターン終了時のラウンドスコア更新処理" median = get_mid(play) winner = list(play).index(median) # round_score[winner] += to_num(median) round_score[winner] += median # to ease of debug return round_score def measure_win_round(round_score): "2ターン目までのラウンドスコアを与えてそのラウンドを得るかの評価関数を返す" def _(*result): score = end_of_turn(result, round_score[:]) if score[0] == get_mid(score): return 1 return 0 return _ def measure_get_game_score(round_score): "2ターン目までのラウンドスコアを与えてそのラウンドに得られるスコアを返す" def _(*result): score = end_of_turn(result, round_score[:]) if score[0] == get_mid(score): return score[0] return 0 return _ def measure_win_game(round_score, game_score): "2ターン目までのラウンドスコアを与えてそのラウンドに得られるスコアを返す" def _(*result): score = end_of_turn(result, round_score[:]) for i in range(3): score[i] += game_score[i] median = get_mid(game_score) result = 2 # 2 is offset not to be negative if score[0] == median: result += 2 if score[1] == median: result -= 1 if score[2] == median: result -= 1 return result return _ # given roundを勝つ確率の高い手を探索する # print think_a_turn([1,2,5,6,7], [3,4,8,9], measure_win_round([0,7,0])) # (21, 3) # given roundでの得点の期待値が最も高い手を探索する # print think_a_turn([1,2,5,6,7], [3,4,8,9], measure_get_game_score([0,7,0])) # (24, 4) # TODO: 複数ターンでの探索 def think_2_turns(unknowns, hand, round_score): max_score = -1 max_hand = None N = len(unknowns) for my in hand: # print "MYHAND", my rest_hand = hand[:] rest_hand.remove(my) score = 0 for o1 in unknowns: for o2 in unknowns: if o1 == o2: continue rest = unknowns[:] rest.remove(o1) rest.remove(o2) # print "ROUND_SCORE", round_score new_round_score = end_of_turn([my, o1, o2], round_score[:]) # print [my, o1, o2], new_round_score, s = think_a_turn(rest, rest_hand, measure_win_round(new_round_score))[0] score += s #print s if score > max_score: max_score = score max_hand = my return (max_score / float(N * (N - 1)), max_hand) def think_a_round(unknowns, hand): max_score = -1 max_hand = None for my in hand: score = 0 for (o1, o2, rest) in get_2_cards_with_rest(unknowns): round_score = end_of_turn([my, o1, o2], [0, 0, 0]) rest_hand = hand[:] rest_hand.remove(my) score += think_2_turns(rest, rest_hand, round_score)[0] if score > max_score: max_score = score max_hand = my return (max_score / float(len(unknowns) * (len(unknowns) - 1)), max_hand) def main(): from time import clock t = clock() print think_a_round([1,2,3,4,5,6,7,8,9,10,11], [12,13,14,15,16]) print clock() - t