Skip to content

Instantly share code, notes, and snippets.

@TotalVerb
Created January 3, 2020 05:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TotalVerb/ef45fa25059ceba22cada06c2c2a5081 to your computer and use it in GitHub Desktop.
Save TotalVerb/ef45fa25059ceba22cada06c2c2a5081 to your computer and use it in GitHub Desktop.
module Rankings
using AutoHashEquals
using Cards
using Compat
import Base: <, <=
@enum RankingClass begin
HighCard
Pair
TwoPair
Triple
Straight
Flush
FullHouse
FourOfAKind
StraightFlush
RoyalFlush
end
@auto_hash_equals struct Ranking
kind::RankingClass
extra::Vector{Int}
end
Ranking(kind) = Ranking(kind, Int[])
a::Ranking < b::Ranking = (a.kind, a.extra) < (b.kind, b.extra)
a::Ranking <= b::Ranking = (a.kind, a.extra) <= (b.kind, b.extra)
function combine(a::Ranking, b::Ranking)
if a > b
# canonicalize order; always a is weaker / equivalent
combine(b, a)
elseif a.kind == Straight && b.kind == Flush
if a.extra[1] == 14
# Royal Flush
Ranking(RoyalFlush)
else
Ranking(StraightFlush, a.extra)
end
elseif a.kind == Pair && b.kind == Triple
Ranking(FullHouse, [b.extra[1], a.extra[1]])
elseif a.kind == Pair && b.kind == Pair
kicker = only(intersect(a.extra[2:end], b.extra[2:end]))
Ranking(TwoPair, [b.extra[1], a.extra[1], kicker])
else
b
end
end
const OF_A_KINDS = [HighCard, Pair, Triple, FourOfAKind]
function evaluatekind(rank, ranks)
num = count(==(rank), ranks)
kickers = reverse(filter(!=(rank), ranks))
Ranking(OF_A_KINDS[num], [rank; kickers])
end
function evaluate(cards)
@assert length(cards) == 5
suits = [Cards.suit(c) for c = cards]
ranks = sort([Cards.rank(c) for c = cards])
# compute the highcard/pair/triple/four/twopair/fullhouse value first
ranking = reduce(combine, evaluatekind.(unique(ranks), Ref(ranks)))
if length(unique(suits)) == 1
ranking = combine(ranking, Ranking(Flush))
end
if ranks[5] == ranks[1] + 4
ranking = combine(ranking, Ranking(Straight, [ranks[5]]))
end
if ranks[5] == 14 && ranks[4] == 5
ranking = combine(ranking, Ranking(Straight, [5]))
end
ranking
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment