Last active
January 18, 2023 19:03
-
-
Save ecounysis/1abdfe352d38ba41c5c4afe467127b16 to your computer and use it in GitHub Desktop.
poker stuff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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