Skip to content

Instantly share code, notes, and snippets.

@rmfbarker
Created September 10, 2013 23:58
Show Gist options
  • Save rmfbarker/6517484 to your computer and use it in GitHub Desktop.
Save rmfbarker/6517484 to your computer and use it in GitHub Desktop.
Poker
import scala.io.Source
// object Main extends App {
// hands in form of '5H 5C 6S 7S KD'
val ROYAL_FLUSH = "TJQKA"
val PROGRESSION = "23456789TJQKA"
def rank(hand: String): (Int, String) = {
if (royalFlush(hand)) (10, "")
else if (straightFlush(hand)) (9, highCard(hand))
else if (fourOfKind(hand)) (8, fourOfKindRank(hand))
else if (fullHouse(hand)) (7, fullHouseRank(hand))
else if (flush(hand)) (6, highCard(hand))
else if (straight(ranks(hand))) (5, highCard(hand))
else if (threeOfKind(hand)) (4, threeOfKindRank(hand))
else if (twoPair(hand)) (3, rankByVolume(hand))
else if (onePair(hand)) (2, rankByVolume(hand))
else (1, highCard(hand))
}
def royalFlush(hand: String): Boolean = sameSuit(hand) && ranks(hand) == ROYAL_FLUSH
def straightFlush(hand: String): Boolean = sameSuit(hand) && straight(ranks(hand))
def fourOfKind(hand: String): Boolean = rankCount(hand) contains 4
def fullHouse(hand: String): Boolean = rankCount(hand) sameElements List(2,3)
def flush(hand: String): Boolean = sameSuit(hand)
def threeOfKind(hand: String): Boolean = rankCount(hand) contains 3
def twoPair(hand: String): Boolean = rankCount(hand) containsSlice List(2,2)
def onePair(hand: String): Boolean = rankCount(hand) contains 2
def highCard(hand: String): String = ranks(hand) reverse
def fourOfKindRank(hand: String): String = rankOfRepeatedCard(hand, 4)
def threeOfKindRank(hand: String): String = rankOfRepeatedCard(hand, 3)
def rankOfRepeatedCard(hand: String, repeats: Int): String = ranks(hand).groupBy(c => c).filter {
case (c,s) => s.size == repeats
}.map{
case (c, s) => s
}.head.distinct
def fullHouseRank(hand: String): String = {
val r = ranks(hand)
val n = r.groupBy(c => c)
r.distinct.sortBy(c => n(c) size).reverse
}
def rankByVolume(hand: String): String = {
val r = ranks(hand)
val n = r.groupBy(c => c)
def pair(a: Char) = n(a).size == 2
def lt(a: Char, b: Char): Boolean =
if (n(a).size == n(b).size) lowerRank(a, b)
else n(a).size < n(b).size
r.distinct.sortWith(lt).reverse
}
def lowerRank(a: Char, b: Char) = PROGRESSION.indexOf(a) < PROGRESSION.indexOf(b)
def sameSuit(hand: String): Boolean = hand.split(" ").map(s => s(1)).distinct.size == 1
def ranks(hand: String): String = {
val r = hand.split(" ").map(s => s(0))
r.sortBy(c => PROGRESSION.toList.indexOf(c)).mkString
}
def straight(hand: String): Boolean =
if (hand.size <= 1) true
else PROGRESSION.contains(hand take 2) && straight(hand drop 1)
def rankCount(hand: String): List[Int] = ranks(hand).groupBy(c => c).map {
case (c, s) => s.size
}.toList.sorted
// TESTS
// ROYAL FLUSH
assert (rank("KD QD TD JD AD")._1 == 10)
assert (royalFlush("KD QD TD JD AD") )
assert ( !royalFlush("KH QH TS JS AD"))
assert ( ranks("JH QH KH TH AH") == ROYAL_FLUSH )
// STRAIGHT FLUSH
assert( straight(ranks("2H 3H 4H 5H 6H")))
assert( highCard("2H 3H 4H 5H 6H") == "65432", highCard("2H 3H 4H 5H 6H"))
assert( straightFlush("2H 3H 4H 5H 6H"))
assert( !straightFlush("2H 3H 4H 5H 7H"))
assert( !straightFlush("2H 3H 4C 5H 6H"))
assert( straight(ranks("JH QH KH TH AH")) )
assert( straightFlush("JH QH KH TH AH"))
assert( rank("2H 3H 4H 5H 6H")._1 == 9)
// FOUR OF A KIND
assert( fourOfKind("5H 5C 8C 5S 5D") )
assert( fourOfKindRank("5H 5C 8C 5S 5D") == "5")
assert( !fourOfKind("5H 5C 8C 5S TD") )
assert( !fourOfKind("3C 3D 3S 9S 9D") )
// STRAIGHT
assert( rank("6H 4H 5C 3H 2H")._1 == 5, rank("6H 4H 5C 3H 2H") )
// FULL HOUSE
assert( fullHouse("5H 6H 5D 6D 5S") )
assert( fullHouseRank("5H 6H 5D 6D 5S") == "56")
// THREE OF A KIND
assert( threeOfKind("5H 6H 5D 6D 5S") )
assert( threeOfKindRank("5H 6H 5D 6D 5S") == "5" )
assert( threeOfKindRank("QH 6H QD 6D QS") == "Q" )
// TWO PAIR
assert( twoPair("5H 6H 5D 6D 9S") )
assert( rankByVolume("5H 6H 5D 6D 9S") == "659", rankByVolume("5H 6H 5D 6D 9S"))
// ONE PAIR
assert( onePair("5H 6H 7D 6D 9S") )
assert( rankByVolume("5H 6H 7D 6D 9S") == "6975" )
// FLUSH rank
assert( highCard("2H QH 3H AH 9H") == "AQ932")
def winner(playerOne: String, playerTwo: String): Boolean = {
val one = rank(playerOne)
val two = rank(playerTwo)
// println(one)
// println(two)
def rankCards(r1: String, r2: String): Boolean = {
if (r1.head != r2.head) PROGRESSION.indexOf(r1.head) > PROGRESSION.indexOf(r2.head)
else rankCards(r1.tail, r2.tail)
}
if (one._1 > two._1) true
else if (one._1 < two._1) false
else rankCards(one._2, two._2)
}
var count = 0
for (line <- Source.fromFile("poker.txt").getLines) {
val one = line take 14
val two = line drop 15
val result = winner(one, two.trim)
println("%s\t%s\t%s\t\t%s\t%s".format(result, one, rank(one), two, rank(two)))
if (result) {
count = count + 1
}
}
println(count)
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment