Skip to content

Instantly share code, notes, and snippets.

@ecounysis
Last active January 18, 2023 19:03
Show Gist options
  • Save ecounysis/1abdfe352d38ba41c5c4afe467127b16 to your computer and use it in GitHub Desktop.
Save ecounysis/1abdfe352d38ba41c5c4afe467127b16 to your computer and use it in GitHub Desktop.
poker stuff
# Poker Hand Analyser Library for Project Euler: Problem 54
from collections import namedtuple
suits = "h,d,c,s".split(",")
faces = "2,3,4,5,6,7,8,9,T,J,Q,K,A"
face = faces.split(',')
class Card(namedtuple('Card', 'face, suit')):
def __repr__(self):
return ''.join(self)
def royal_flush(hand):
royalface = "TJQKA"
# sort the cards based on the face rank of each card
ordered = sorted(hand, key=lambda card: (faces.index(card.face), card.suit))
first_card = ordered[0]
other_cards = ordered[1:]
# check if all are of the same suit
if all(first_card.suit == card.suit for card in other_cards):
# check if they are in sequential order
# compare the ordered faces substring with the face list (which is converted to string)
if ''.join(card.face for card in ordered) in royalface:
return 'royal-flush', ordered[-1].face
return False
def straight_flush(hand):
# sort the cards based on the face rank of each card
ordered = sorted(hand, key=lambda card: (faces.index(card.face), card.suit))
first_card = ordered[0]
other_cards = ordered[1:]
# check if all are of the same suit
if all(first_card.suit == card.suit for card in other_cards):
# check if they are in sequential order
# compare the ordered faces substring with the face list (which is converted to string)
if ''.join(card.face for card in ordered) in ''.join(face):
return 'straight-flush', ordered[-1].face
return False
def four_of_a_kind(hand):
allfaces = [f for f,s in hand]
# create a unique set of ranks
uniqueRanks = set(allfaces)
# if there are more than 2 ranks, it's not four of a kind
if len(uniqueRanks) != 2:
return False
for f in uniqueRanks:
# if there are 4 faces, it is four of a kind
if allfaces.count(f) == 4:
uniqueRanks.remove(f)
return "four-of-a-kind", f
return False
def frequency(s):
freq = {}
for i in s:
if i in freq:
freq[i] += 1
else:
freq[i] = 1
return freq
def full_house(hand):
allfaces = [f for f,s in hand]
rankFrequency = frequency(allfaces)
# if there are 2 types of ranks and there's a card with 1 pair and 3 of a kind
if len(rankFrequency) == 2 and (rankFrequency.values()[0] == 2 and rankFrequency.values()[1] == 3):
return 'full-house'
return False
def flush(hand):
allfaces = [f for f,s in hand]
first_card = hand[0]
other_cards = hand[1:]
if all(first_card.suit == card.suit for card in other_cards):
return 'flush', sorted(allfaces, key=lambda f: face.index(f), reverse=True)
return False
def straight(hand):
ordered = sorted(hand, key=lambda card: (faces.index(card.face), card.suit))
if ''.join(card.face for card in ordered) in ''.join(face):
return 'straight', ordered[-1].face
return False;
def three_of_a_kind(hand):
allfaces = [f for f,s in hand]
uniqueRanks = set(allfaces)
if len(uniqueRanks) != 3:
return False
for f in uniqueRanks:
if allfaces.count(f) == 3:
uniqueRanks.remove(f)
return "three-of-a-kind", f
return False;
def two_pair(hand):
allfaces = [f for f,s in hand]
allftypes = set(allfaces)
# collect pairs
pairs = [f for f in allftypes if allfaces.count(f) == 2]
# if there are more than two pairs
if len(pairs) != 2:
return False
p1, p2 = pairs
# get the difference using sets
other_cards = [(allftypes - set(pairs)).pop()]
return 'two-pair', pairs + other_cards if(face.index(p1) > face.index(p2)) else pairs[::-1] + other_cards
def one_pair(hand):
allfaces = [f for f,s in hand]
allftypes = set(allfaces)
# collect pairs
pairs = [f for f in allftypes if allfaces.count(f) == 2]
# if there's more than one pair
if len(pairs) != 1:
return False
allftypes.remove(pairs[0])
return 'one-pair', pairs + sorted(allftypes, key=lambda f: face.index(f), reverse=True)
def high_card(hand):
# collect all faces from each card
allfaces = [f for f,s in hand]
#sort the faces and show the highest card
return "high_card", sorted(allfaces, key=lambda f: allfaces.index(f), reverse=True)[0]
def create_hand_tuple(cards = "5D 8C 9S JS AC"):
hand = []
for card in cards.split():
face, suit = card[:-1], card[-1]
hand.append(Card(face, suit))
return hand;
# functions
handrankorder = (royal_flush,straight_flush,four_of_a_kind,full_house,
flush,straight,three_of_a_kind,two_pair,
one_pair,high_card)
def determine_rank(cards):
hand = create_hand_tuple(cards)
for ranker in handrankorder:
rank = ranker(hand)
if rank:
break
return rank
import itertools
import random
import collections
#from poker import *
class Result():
def __init__(self, resultType, cards, success):
self.resultType = resultType
self.cards = cards
self.success = success
def __repr__(self):
if (self.success):
return self.resultType
else:
return "no " + self.resultType
def __str__(self):
if (self.success):
return self.resultType+":"+str(self.cards)
else:
return "no " + self.resultType
def deck():
suits = ['s','h','d','c']
values = ['2','3','4','5','6','7','8','9','T','J','Q','K','A']
cards = []
for s in suits:
for v in values:
c = v + s
cards.append(c)
return cards
def shuffle(d):
random.shuffle(d)
def deal():
d = deck()
shuffle(d)
hand = [d.pop(), d.pop()]
common = [d.pop() for i in range(5)]
return (hand, common)
def rank(card):
return card[0]
def suit(card):
return card[1]
def rankSort(v, acesHi=True):
if (v=="A"):
if (acesHi):
return int(14)
else:
return int(1)
if (v=="K"):
return int(13)
if (v=="Q"):
return int(12)
if (v=="J"):
return int(11)
if (v=="T"):
return int(10)
else:
return int(v)
def ranksKey(card, acesHi=True):
v = rank(card)
if (v=="A"):
if (acesHi):
return int(14)
else:
return int(1)
if (v=="K"):
return int(13)
if (v=="Q"):
return int(12)
if (v=="J"):
return int(11)
if (v=="T"):
return int(10)
else:
return int(v)
def acesHi(card):
return ranksKey(card)
def acesLo(card):
return ranksKey(card, False)
def straightAlgo(cards, algo, straightSize=5):
retVal = []
cards.sort(key=algo)
c0 = algo(cards[0])
stCards = [cards[0]]
stSize = 1
for c in cards[1:]:
if(int(algo(c)) == (c0+1)):
stSize += 1
c0 = algo(c)
stCards.append(c)
else:
stCards = [c]
stSize = 1
c0 = algo(c)
if(stSize >= straightSize):
retVal.append(Result("straight:" + str(rank(c)) + "hi", stCards, True))
return retVal
def straight(cards, handSize=5):
v0 = straightAlgo(cards, acesHi, handSize)
v1 = straightAlgo(cards, acesLo, handSize)
if v0 == v1:
return v0
else:
return v0+v1
def flush(cards, handSize=5):
suits = collections.Counter([suit(i) for i in cards])
commonSuits = suits.most_common()
cs = [card for card in cards if suit(card) == commonSuits[0][0]]
#print(cs)
#print(commonSuits)
if commonSuits[0][1] >= handSize:
return Result("flush:"+commonSuits[0][0], cs, True)
else:
return Result("flush", None, False)
def matches(cards):
ranks=collections.Counter([rank(i) for i in cards])
commonRanks = ranks.most_common()
results = []
for i in range(len(commonRanks)):
if (commonRanks[i][1] > 1):
num = str(commonRanks[i][1])
if (num == "2"):
s = "pair"
else:
s = num + "oak"
s += ":" + str(commonRanks[i][0])
cds = [c for c in cards if rank(c)==commonRanks[i][0]]
results.append(Result(s, cds, True))
if (num == 4):
break
return results
def evalhand(cards, handSize=5):
results = []
aStraight = False
mt=matches(cards)
st=straight(cards, handSize)
fl=flush(cards, handSize)
if(len(mt)>0):
results.append(mt)
if(len(st)>0):
results.append(st)
aStraight = True
if(fl.success):
results.append(fl)
if(aStraight):
stFlush = straight(fl.cards, 5)
if (len(stFlush) > 0):
results.append(Result("stfl", fl.cards, True))
presentable_results = []
for result in results:
if type(result) is list:
for r in result:
presentable_results.append(r)
else:
presentable_results.append(result)
return presentable_results
def wadayagot(cards):
eh = evalhand(cards)
result = ""
resultWords = [res.resultType for res in eh if res.success]
results = collections.Counter([i[0:4] for i in resultWords])
def results2(rw4):
return [i[5:6] for i in resultWords if i[0:4] == rw4]
def results3(rw4):
return [i[6:7] for i in resultWords if i[0:4] == rw4]
mostCommon = results.most_common()
if (results["stfl"] > 0):
result = "straight flush"
elif (results["4oak"] > 0):
result = "four of a kind"
result += ":" + results2("4oak")[0]
elif (results["3oak"] > 1):
result = "full house"
vals = results2("3oak")
vals.sort(reverse=True, key=rankSort)
result += ":" + vals[0] + " and " + vals[1]
elif (results["3oak"] > 0 and results["pair"] > 0): # 2 - 3oak full house
result = "full house"
vals = results2("3oak")
vals.sort(reverse=True, key=rankSort)
result += ":" + vals[0] + " and "
vals = results2("pair")
vals.sort(reverse=True, key=rankSort)
result += vals[0]
elif (results["flus"] > 0):
result = "flush:" + results3("flus")[0]
elif (results["stra"] > 0):
result = "straight"
elif (results["3oak"] > 0):
result = "three of a kind:"+ results2("3oak")[0]
elif (results["pair"] > 1): # two pair
result = "two pair"
vals = results2("pair")
vals.sort(reverse=True, key=rankSort)
result += ":" + vals[0] + " and " + vals[1]
elif (results["pair"] > 0):
result = "pair"
vals = results2("pair")
vals.sort(reverse=True, key=rankSort)
result += ":" + results2("pair")[0]
else:
result = "high card"
cards.sort(reverse=True, key=acesHi)
result += ":"+cards[0]
return result
def test():
(h, c) = deal()
hc = h + c
return (h, c, evalhand(hc))
def test2():
(h, c) = deal()
hc = h + c
print (h, c, wadayagot(hc))
def cds():
(h, c) = deal()
return h + c
def toCards(str):
return str.split(" ")
def runMonteCarlo(xTimes, fname):
f=open("MonteCarlo."+str(fname)+".csv","w")
f.write("hand,flop,turn,river,best_hand\n")
for i in range(xTimes):
d = deck()
shuffle(d)
hand = [d.pop(), d.pop()]
flop = [d.pop() for i in range(3)]
turn = [d.pop()]
river = [d.pop()]
cards = hand + flop + turn + river
wyg = wadayagot(cards)
f.write('"' + " ".join(hand) + '","' +" ".join(flop)+'","'+" ".join(turn)+'","'+" ".join(river)+'","'+wyg+'"\n')
f.close()
#for i in range(1):
# runMonteCarlo(100000, i+1000)
tc=toCards('2d 5s 9d 3d 4d Jd 8s')
wadayagot(tc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment