import random, collections
SAMPLES = 1000000
OUTPUT_PERIOD = 100000
PRECISION = 6
ranks = ['A','T','K','Q','J']
suits = ['C','D','H','S']
cards = [(r,s) for r in ranks for s in suits]*4
def findMinRankOfSuit(cardCount, suit):
"""Return the minimum number of any rank in the specified suit."""
minCount = 40
for r in ranks:
if cardCount[(r,suit)] == 0:
# There are no runs in this suit because a card is missing
return 0
minCount = min(cardCount[(r,suit)], minCount)
return minCount
def typeOfRun(cardCount):
"""Return 0 if there are no runs, 1 if the largest run is a single, ... 4 if
the hand is a quad-run."""
largestRun = 0
for s in suits:
typeOfRunInSuit = findMinRankOfSuit(cardCount, s)
largestRun = max(typeOfRunInSuit, largestRun)
return largestRun
def findTypeOfMarriageInSuit(cardCount, suit):
"""Return the number of marriages in the given suit."""
return min(cardCount[('K',suit)], cardCount[('Q',suit)])
def typeOfMarriage(cardCount):
"""Return 0 if there are no marriages, 1 if the largest marriage is a
single, ... 4 if the hand contains a quad-marriage."""
largestMarriage = 0
for s in suits:
typeOfMarriageInSuit = findTypeOfMarriageInSuit(cardCount, s)
largestMarriage = max(typeOfMarriageInSuit, largestMarriage)
return largestMarriage
def typeOfPinochle(cardCount):
"""Return 0 if there are no marriages, 1 if the largest marriage is a
single, ... 4 if the hand contains a quad-marriage."""
return min(cardCount[('J','D')], cardCount[('Q','S')])
def typeOfAceAround(cardCount):
"""Return 0 if there are no ace arounds, 1 if the largest ace around is a
single, ... 4 if the hand contains a quad-ace around."""
minAround = 4
for s in suits:
minAround = min(cardCount[('A',s)], minAround)
return minAround
def typeOfRoundhouse(cardCount):
"""Return the number of roundhouses (marriage in each suit)."""
smallestMarriage = 4
for s in suits:
typeOfMarriageInSuit = findTypeOfMarriageInSuit(cardCount, s)
smallestMarriage = min(typeOfMarriageInSuit, smallestMarriage)
return smallestMarriage
def displayHeader():
types = ['NONE', 'SINGLE', 'DOUBLE', 'TRIPLE', 'QUAD']
probabilityHeadingFormat = '{:^'+str(PRECISION+2)+'}'
stringFormat = '| MELD TYPE | ' + ' | '.join([probabilityHeadingFormat]*5) + ' |'
print stringFormat.format(*types)
def display(label, count):
values = [label] + [count[i] / float(SAMPLES) for i in range(4+1)]
probabilityFormat = '{:0.'+str(PRECISION)+'f}'
stringFormat = '| {:<11} | ' + ' | '.join([probabilityFormat]*5) + ' |'
print stringFormat.format(*values)
runCount = collections.defaultdict(int)
marriageCount = collections.defaultdict(int)
pinochleCount = collections.defaultdict(int)
aceAroundCount = collections.defaultdict(int)
roundhouseCount = collections.defaultdict(int)
for i in xrange(SAMPLES):
random.shuffle(cards)
hand = cards[:20]
cardCount = collections.defaultdict(int)
for h in hand:
cardCount[h] += 1
runCount[typeOfRun(cardCount)] += 1
marriageCount[typeOfMarriage(cardCount)] += 1
pinochleCount[typeOfPinochle(cardCount)] += 1
aceAroundCount[typeOfAceAround(cardCount)] += 1
roundhouseCount[typeOfRoundhouse(cardCount)] += 1
if i % OUTPUT_PERIOD == OUTPUT_PERIOD - 1:
print i / OUTPUT_PERIOD
print 'R: ', [float(runCount[j]) / i for j in range(4+1)]
print 'M: ', [float(marriageCount[j]) / i for j in range(4+1)]
print 'P: ', [float(pinochleCount[j]) / i for j in range(4+1)]
print 'A: ', [float(aceAroundCount[j]) / i for j in range(4+1)]
print 'H: ', [float(roundhouseCount[j]) / i for j in range(4+1)]
print
displayHeader()
display('Runs', runCount)
display('Marriages', marriageCount)
display('Pinochles', pinochleCount)
display('Ace Arounds', aceAroundCount)
display('Roundhouses', roundhouseCount)
# Output from 1,000,000 runs:
#| MELD TYPE | NONE | SINGLE | DOUBLE | TRIPLE | QUAD |
#| Runs | 0.522113 | 0.476676 | 0.001211 | 0.000000 | 0.000000 |
#| Marriages | 0.055983 | 0.716652 | 0.221239 | 0.006113 | 0.000013 |
#| Pinochles | 0.528127 | 0.411803 | 0.058548 | 0.001521 | 0.000001 |
#| Ace Arounds | 0.791536 | 0.206261 | 0.002203 | 0.000000 | 0.000000 |
#| Roundhouses | 0.967973 | 0.032027 | 0.000000 | 0.000000 | 0.000000 |