views:

102

answers:

3

I am writing a dice game simulator in Python. I represent a roll by using a list containing integers from 1-6. So I might have a roll like this:

[1,2,1,4,5,1]

I need to determine if a roll contains scoring combinations, such as 3 of a kind, 4 of a kind, 2 sets of 3, and straights.

Is there a simple Pythonic way of doing this? I've tried several approaches, but they all have turned out to be messy.

+4  A: 

Reorganize into a dict with value: count and test for presence of various patterns.

Ignacio Vazquez-Abrams
Clever. There might be some tricks to do with making a "set" out of the list as well.
dkamins
In python 2.7 (or 3.1) theres a Counter class in the collections module which will do this for you. `collections.Counter([1, 2, 1, 4, 5, 1])` will behave like that `value : count` dictionary.
AndrewF
+1  A: 

There are two ways to do this:

def getCounts(L):
    d = {}
    for i in range(1, 7):
        d[i] = L.count(i)
    return d # d is the dictionary which contains the occurrences of all possible dice values
             # and has a 0 if it doesn't occur in th roll

This one is inspired by Ignacio Vazquez-Abrams and dkamins

def getCounts(L):
    d = {}
    for i in set(L):
        d[i] = L.count(i)
    return d # d is the dictionary which contains the occurrences of 
             # all and only the values in the roll
inspectorG4dget
+2  A: 

I have written code like this before (but with cards for poker). A certain amount of code-sprawl is unavoidable to encode all of the rules of the game. For example, the code to look for n-of-a-kind will be completely different from the code to look for a straight.

Let's consider n-of-a-kind first. As others have suggested, create a dict containing the counts of each element. Then:

counts = sorted(d.values())
if counts[-1] == 4:
   return four_of_a_kind
if counts[-1] and counts[-2] == 3:
   return two_sets_of_three
# etc.

Checking for straights requires a different approach. When checking for n-of-a-kind, you need to get the counts and ignore the values. Now we need to examine the values and ignore the counts:

ranks = set(rolls)
if len(ranks) == 6: # all six values are present
    return long_straight
# etc.

In general, you should be able to identify rules with a similar flavor, abstract out code that helps with those kinds of rules, and then write just a few lines per rule. Some rules may be completely unique and will not be able to share code with other rules. That's just the way the cookie crumbles.

Daniel Stutzbach