'''
Created on Feb 14,2011

@author: ola, rcd, apsd
'''
import random


def toCardString(card):
    """
    Given a card in list form, return a string that represents it.
    """
    rankStrings = ["ace","two","three","four","five","six","seven",
                   "eight","nine","ten","jack","queen","king"]
    suitStrings = ["spades", "hearts", "diamonds","clubs"]
    return rankStrings[card[0]] + " of " + suitStrings[card[1]]


def get_deck():
    """
    Returns a deck of all 52 cards, unshuffled. 
    Cards are represented as [rank, suit] pairs, 
    and the deck is an array of such lists.
    """
    d = []
    for rank in range(0,13):
        for suit in range(0,4):
            d.append([rank,suit])
    return d


def get_hand(deck):
    """
    Given a deck, returns a list containing 5 random cards from the deck.
    It also changes the order of cards within the deck.
    """
    random.shuffle(deck)
    return deck[0:5]


def print_hand(hand):
    """
    Given a hand, print a human-readable version of it.
    """
    print '[',
    for card in hand:
        print toCardString(card),',',
    print ']'


def get_rank_counts(hand):
    """
    Given a hand of cards, returns a list.
    The nth element in the list is the count of
    how many cards in the hand had rank n.
    e.g., list[3] = # occurrences of a 3, list[11] = # occurrences of jack
    """
    counts = [0]*13
    for card in hand:
        rank = card[0]
        counts[rank] += 1
    return counts


def is_pair(hand):
    """
    Given a hand, returns True iff the hand would be considered a "pair" in poker. 
    Note that hands which rank higher (such as a full house) do not count as being a pair.
    """
    ranks = get_rank_counts(hand)
    # Not only do we need a pair, we need to make sure the other
    # cards don't have the same rank.
    return ranks.count(2) == 1 and ranks.count(1) == 3

def is_two_pair(hand):
    """
    Given a hand, returns True iff the hand would be considered "two pair" in poker. 
    Note that hands which rank higher (such as a full house) do not count as being a pair.
    """
    # TODO: Remove this line and replace with your implementation
    return False

def is_three_of_a_kind(hand):
    """
    Given a hand, returns True iff the hand would be considered "three of a kind" in poker.
    Note that hands which rank higher (such as a full house) do not count as being a pair.
    """
    # TODO: Remove this line and replace with your implementation
    return False

def is_full_house(hand):
    """
    Given a hand, returns True iff the hand would be considered a "full house" in poker.
    """
    # TODO: Remove this line and replace with your implementation
    return False

def is_naive_straight(hand):
    """
    Determines whether all cards in the hand are consecutive.
    This function does not care whether the cards are also a flush.
    """
    # TODO: Remove this line and replace with your implementation
    return False

def is_naive_flush(hand):
    """
    Determines whether all cards in the hand have the same suit.
    This function does not care whether the cards are also a straight.
    """
    # TODO: Remove this line and replace with your implementation
    return False

def is_straight(hand):
    """
    Given a hand, returns True iff the hand would be considered "straight" in poker.
    In particular, it only returns True if the hand is a straight but not a straight flush.
    """
    return is_naive_straight(hand) and not is_naive_flush(hand)

def is_flush(hand):
    """
    Given a hand, returns True iff the hand would be considered "flush" in poker. 
    In particular, it only returns True if the hand is a flush but not a straight flush.
    """
    return is_naive_flush(hand) and not is_naive_straight(hand)



# Each of these arrays has the same length, and the elements at 
# the same index of each of them correspond with each other. For
# example, the first element of handNames is "pair," the first
# element of handCounts represents the number of hands generated
# that were pairs, and the first element of handFunctions is a
# function that determines if a hand is a pair.
# This is a list of functions! Sweet!

def simulate(n):
    '''
    Simulate dealing n poker hands
    '''
    handFunctions = [is_pair, is_two_pair, is_three_of_a_kind, is_full_house, is_straight, is_flush]
    handNames = [' '.join(f.func_name.split('_')[1:]) for f in handFunctions]
    handCounts = [0]*len(handFunctions)
    # simulate random dealings
    deck = get_deck()
    for i in range(0, n):
        hand = get_hand(deck)
        for i,func in enumerate(handFunctions):
            if func(hand):
                handCounts[i] += 1
    # print results
    for i in range(len(handNames)):
        chances = 1.0 * handCounts[i] / n
        print handNames[i] + ": " + str(chances)


simulate(10000)
