Created
January 3, 2020 05:27
-
-
Save TotalVerb/ef45fa25059ceba22cada06c2c2a5081 to your computer and use it in GitHub Desktop.
This file contains 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
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