Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A little program that calculates poker probabilities.
//
// main.swift
// poker-head
//
// Created by Jan on 14.04.17.
// Copyright © 2017 Jan Hünermann. All rights reserved.
//
import Foundation
// out – A card that improves our hand
var players = 5
let cardsPerPlayer = 2
let pokerDeck = 52
let pokerFlop = 3 // number of cards shown after flop
let pokerTurn = 4 // number of cards shown after turn
// Only works for n ∈ [0; 20[
func binomial(_ n: Int, _ k: Int) -> UInt64 {
if (k == 0 || k == n) {
return 1
}
var coeff: UInt64 = 1
for x in (n-k+1)...(n) {
coeff *= UInt64(x)
}
for x in 1...k {
coeff /= UInt64(x)
}
return coeff
}
// What is the probability that there are exactly OS outs in the stack?
// Calculates this via a tree
func probabilityForPrecisely(numberOfOutsInStack OS: Int, numberOfTotalOuts O: Int, shownCards S: Int, distributedCards: Int = 0, inHand X1: Int = 0, inStack X2: Int = -1) -> Double {
var X2 = X2
if (X2 == -1) {
X2 = O
}
// End of tree; this branch should be zero unless it's number of outs in stack is equal to the number we are looking for
if distributedCards == (players - 1) * cardsPerPlayer {
if X2 == OS {
return 1.0
}
else {
return 0.0
}
}
// There are no outs in the stack anymore
if (X2 == 0) {
return OS != 0 ? 0.0 : 1.0
}
let unknownCards = pokerDeck - distributedCards - S - cardsPerPlayer
// Ok, player draws one of our outs
let playerDrawsOut = Double(X2) / Double(unknownCards)
* probabilityForPrecisely(numberOfOutsInStack: OS, numberOfTotalOuts: O, shownCards: S, distributedCards: distributedCards + 1, inHand: X1 + 1, inStack: X2 - 1)
// Ok, player does not draw one of our outs
let playerDrawsNoOut = (1.0 - Double(X2) / Double(unknownCards))
* probabilityForPrecisely(numberOfOutsInStack: OS, numberOfTotalOuts: O, shownCards: S, distributedCards: distributedCards + 1, inHand: X1, inStack: X2)
// Sum
return playerDrawsOut + playerDrawsNoOut
}
// The probability that given S shown cards and O outs, the next card will be one
// of your desires (it will be an out)
func singleProbability(outs O: Int, numberOfShownCards S: Int = 3) -> Double {
if (O == 0) {
return 0.0
}
// Size of stack
let stack = pokerDeck - players * cardsPerPlayer - S
// Output
var cumulative = 0.0
for x in 0...O {
// P(there are exactly x outs in stack)
let binom = probabilityForPrecisely(numberOfOutsInStack: x, numberOfTotalOuts: O, shownCards: S)
// P(there are exactly x outs in stack) * (x outs / stack size)
cumulative += binom * (Double(x) / Double(stack))
}
return cumulative
}
// Sum probability that one of your outs will come after flop
func turnAndRiverProb(outs O: Int) -> Double {
let a1 = singleProbability(outs: O, numberOfShownCards: pokerFlop)
let b1 = singleProbability(outs: O, numberOfShownCards: pokerTurn)
let b2 = singleProbability(outs: O - 1, numberOfShownCards: pokerTurn)
// P(out on turn) + P(out on river) + P(out on turn AND out on river)
return a1 * (1-b2) + (1-a1) * b1 + a1 * b2
}
func riverProb(outs O: Int) -> Double {
return singleProbability(outs: O, numberOfShownCards: pokerTurn)
}
print("Welcome to POKER HEAD")
print("I will calculate probabilities")
print("******")
print("How many players do you want me to calculate for?")
players = Int(readLine()!)!
print("Ok, \(players) players. Go ahead and ask me for probabilities.")
print("Valid commands :")
print("after-flop <outs>")
print("on-river <outs>")
while (true) {
let input = readLine()!.components(separatedBy: " ")
if (input.count != 2) {
print("Incorrect input")
continue
}
let cmd = input[0].lowercased()
let outs = Int(input[1])!
switch cmd {
case "on-river": print(riverProb(outs: outs) * 100, "%")
case "after-flop": print(turnAndRiverProb(outs: outs) * 100, "%")
default: print("Incorrect input")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment