In [1]:
def memoize(f):
    """ Memoization decorator for functions taking one or more arguments. """
    class memodict(dict):
        def __init__(self, f):
            self.f = f
        def __call__(self, *args):
            return self[args]
        def __missing__(self, key):
            ret = self[key] = self.f(*key)
            return ret
    return memodict(f)

In [2]:
# Solve Settlers of Catan
class Board(object):
    """
    The.
    """

In [6]:
# TODO:
#   Handle DevCard
WOOD, CLAY, ORE, GRAIN, SHEEP = 'WOOD', 'CLAY', 'ORE', 'GRAIN', 'SHEEP'
ROAD, SETTLEMENT, CITY, DEVCARD = 'ROAD', 'SETTLEMENT', 'CITY', 'DEVCARD' 
possible_cards = [WOOD, CLAY, ORE, GRAIN, SHEEP]
buildable_units = [ROAD, SETTLEMENT, CITY]
buildable_unit_cost = {ROAD: {WOOD: 1, CLAY:1},
                       SETTLEMENT: {WOOD: 1, CLAY: 1, GRAIN: 1, SHEEP: 1},
                       CITY: {GRAIN: 2, ORE: 3}}
PASS = 'PASS'

def possible_build_actions(hand):
    """
    Returns the possible actions for a hand. 
    
    Args:
        hand: dict, maps from CARD -> Count.
    """
    return [unit for unit in buildable_units 
            if all(card in hand and hand[card] >= cost 
                   for card, cost in buildable_unit_cost[unit].iteritems())]

# Simple tests.
assert possible_build_actions({WOOD: 1, CLAY:1}) == [ROAD]
assert possible_build_actions({ORE: 3, GRAIN: 2}) == [CITY]
assert possible_build_actions({WOOD: 1, CLAY: 1, SHEEP: 1, GRAIN: 1}) == [ROAD, SETTLEMENT]

In [7]:
def solve(current_hand):
    """Find the minumum number of moves required to win the input game."""
    # Add expected value to hand.
    possible_actions = possible_build_actions(current_had) + [PASS]
    for action in


  File "<ipython-input-7-533b9cfe69b1>", line 5
    for action in
                  ^
SyntaxError: invalid syntax

In [31]:
import numpy as np
np.array([v for v in val.values() for val in {'k': 'b'}.values()])


Out[31]:
array(['b'], 
      dtype='|S1')

In [ ]: