HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Poker probabilities finder

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pokerprobabilitiesfinder

Problem

This code finds the probabilities of the various scores in Poker. It uses a Monte Carlo approach, in which, two million (\$2 \times 10^{6}\$) hands are simulated and evaluated, not an exhaustive search.

According to Wikipedia, my results are accurate.

I strived to avoid over-engineering, where the only tricky part is poker_value as it uses a bit of metaprogramming, but it was necessary to avoid duplication.

I am interested in performance improvements only if they do not hurt readability and straightforwardness.

An example output is:

Poker probabilities:
('nothing', 50.1837)
('pair', 42.1968)
('two_pair', 4.77195)
('three_of_a_kind', 2.18145)
('straight', 0.3568)
('flush', 0.198)
('full_house', 0.08485)
('four_of_a_kind', 0.02505)
('straight_flush', 0.0014)
Time taken: 107.4311831


The code:

```
from __future__ import division
from collections import namedtuple, Counter
import doctest
import random
import time

CARDS_PER_HAND = 5
VALUES = 13
KINDS = 4
ACCURACY = 2 * 10 ** 6

Card = namedtuple("Card", ["value", "kind"])

def all_equal(lst):
"""
>>> all_equal([1,1,1,1])
True
>>> all_equal([1,2,3])
False
"""
return len(set(lst)) == 1

def couples(lst):
"""
>>> couples([1,5,7])
[[1, 5], [5, 7]]
"""
return [ [curr, lst[index + 1]]
for index, curr in enumerate(lst[:-1])]

def one_by_one_increasing(lst):
"""
>>> one_by_one_increasing([5, 6, 7, 8])
True
"""
return all(nexxt == previous + 1
for previous, nexxt in couples(lst))

def most_common(lst):
"""
>>> most_common([1,2,2,2,3])
2
"""
return Counter(lst).most_common()[0][0]

def most_common_count(lst):
"""
>>> most_common_count([4,4,4,1,1])
3
>>> most_common_count([7,3,1,7,8])
2
"""
return lst.count(most_common(lst))

def first_true(arg, funcs):
"""
>>> def false(n): return False
>>> def even(n): return n % 2 == 0
>>> first_true(14, [false, even

Solution

Your code looks good and the logic is well separated in testable (and tested) functions.

A few details :

-
Maybe it would make sense for all_equal(lst) to return True for an empty list (just like the all builtin returns True for empty iterable). You'd just need to replace == 1 by

-
In
couples, you are using explicitely the index to iterate over consecutive arrays. You'll find various other ways to do so. I'll let you pick the one you prefer (after performing some benchmark if needed). Also, because of the way you use it, there might not be a need for returning a newly constructed list, an iterable would be enough.

-
Your implemement of
most_common should pass 1 as a parameter to most_common so that it doesn't generate the whole list so that you are mostly ignoring.

-
Your implementation of
most_common_count is not really efficient : the most_common() function already returns the count and you are simply ignoring it.

I think the right way to do it would be to have a most_common() function returning a tuple
(item, count)`. Also you should probably handle the cases where different items are the most common.

I'll try to continue.

Context

StackExchange Code Review Q#97626, answer score: 4

Revisions (0)

No revisions yet.