Skip to content

Commit

Permalink
Merge #26
Browse files Browse the repository at this point in the history
26: Unroll combinations, remove vector interface r=charleskawczynski a=charleskawczynski

Fix #25

Co-authored-by: Charles Kawczynski <kawczynski.charles@gmail.com>
  • Loading branch information
bors[bot] and charleskawczynski authored May 16, 2021
2 parents e7bae73 + 388f13d commit a3a06cf
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PokerHandEvaluator"
uuid = "18ed25b1-892a-4a3b-b8fc-1036dc9a6a89"
authors = ["Charles Kawczynski <kawczynski.charles@gmail.com>"]
version = "0.1.0"
version = "0.1.1"

[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Expand Down
4 changes: 2 additions & 2 deletions perf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ N_evals = 10^5 # ~4% of all combinations
### Only collect hands if N_evals has changed:
(@isdefined N_old) || (N_old = N_evals)
# length(combinations(full_deck(), 5)) = 2598960
N_old == N_evals || (hands = collect(combinations(full_deck(), 5))[1:N_evals])
(@isdefined hands) || (hands = collect(combinations(full_deck(), 5))[1:N_evals])
N_old == N_evals || (hands = Tuple.(collect(combinations(full_deck(), 5))[1:N_evals]))
(@isdefined hands) || (hands = Tuple.(collect(combinations(full_deck(), 5))[1:N_evals]))
N_old = N_evals
###

Expand Down
69 changes: 62 additions & 7 deletions src/PokerHandEvaluator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ struct FullHandEval{HT <: AbstractHandType, AC <: Tuple, TC <: Tuple} <: Abstrac
FullHandEval(player_cards::Tuple, table_cards::Tuple) =
FullHandEval((player_cards..., table_cards...))
FullHandEval(all_cards...) = FullHandEval(all_cards)
FullHandEval(all_cards::Vector) = FullHandEval(Tuple(all_cards))
function FullHandEval(all_cards::Tuple)
@assert 5 length(all_cards) 7
rank, hand_type, best_cards = evaluate_full(all_cards)
Expand Down Expand Up @@ -127,7 +126,6 @@ struct CompactHandEval{HT <: AbstractHandType} <: AbstractHandEvaluation
CompactHandEval(player_cards::Tuple, table_cards::Tuple) =
CompactHandEval((player_cards..., table_cards...))
CompactHandEval(all_cards...) = CompactHandEval(all_cards)
CompactHandEval(all_cards::Vector) = CompactHandEval(Tuple(all_cards))
function CompactHandEval(all_cards::Tuple)
@assert 5 length(all_cards) 7
rank, hand_type = evaluate_compact(all_cards)
Expand All @@ -139,12 +137,61 @@ to_tuple(th::CompactHandEval) = (th.rank, th.hand_type)
hand_rank(th::CompactHandEval) = th.rank
hand_type(th::CompactHandEval) = th.hand_type

"""
combinations_6_choose_5(tup::Tuple)
Unroll `Combinatorics.combinations` for all 5-card
combinations given 6 cards.
"""
function combinations_6_choose_5(tup::Tuple)
@assert length(tup) == 6
return (
(tup[1], tup[2], tup[3], tup[4], tup[5]),
(tup[1], tup[2], tup[3], tup[4], tup[6]),
(tup[1], tup[2], tup[3], tup[5], tup[6]),
(tup[1], tup[2], tup[4], tup[5], tup[6]),
(tup[1], tup[3], tup[4], tup[5], tup[6]),
(tup[2], tup[3], tup[4], tup[5], tup[6]),
)
end

"""
combinations_7_choose_5(tup::Tuple)
Unroll `Combinatorics.combinations` for all 5-card
combinations given 7 cards.
"""
function combinations_7_choose_5(tup::Tuple)
@assert length(tup) == 7
return (
(tup[1], tup[2], tup[3], tup[4], tup[5]),
(tup[1], tup[2], tup[3], tup[4], tup[6]),
(tup[1], tup[2], tup[3], tup[4], tup[7]),
(tup[1], tup[2], tup[3], tup[5], tup[6]),
(tup[1], tup[2], tup[3], tup[5], tup[7]),
(tup[1], tup[2], tup[3], tup[6], tup[7]),
(tup[1], tup[2], tup[4], tup[5], tup[6]),
(tup[1], tup[2], tup[4], tup[5], tup[7]),
(tup[1], tup[2], tup[4], tup[6], tup[7]),
(tup[1], tup[2], tup[5], tup[6], tup[7]),
(tup[1], tup[3], tup[4], tup[5], tup[6]),
(tup[1], tup[3], tup[4], tup[5], tup[7]),
(tup[1], tup[3], tup[4], tup[6], tup[7]),
(tup[1], tup[3], tup[5], tup[6], tup[7]),
(tup[1], tup[4], tup[5], tup[6], tup[7]),
(tup[2], tup[3], tup[4], tup[5], tup[6]),
(tup[2], tup[3], tup[4], tup[5], tup[7]),
(tup[2], tup[3], tup[4], tup[6], tup[7]),
(tup[2], tup[3], tup[5], tup[6], tup[7]),
(tup[2], tup[4], tup[5], tup[6], tup[7]),
(tup[3], tup[4], tup[5], tup[6], tup[7]),
)
end

"""
evaluate(cards::Card...)
evaluate(::Card,::Card,::Card,::Card,::Card[,::Card,::Card])
evaluate(::Tuple{Card,Card,Card,Card,Card[,Card,Card]})
evaluate(::Vector{Card})
Evaluates 5, 6, and 7-card hands using
[`evaluate5`](@ref). This is done by using
Expand All @@ -163,13 +210,17 @@ evaluate_full(t::Tuple{<:Card,<:Card,<:Card,<:Card,<:Card}) = (evaluate5(t)...,

# Wrapper for 6 card hands:
function evaluate_full(t::Tuple{<:Card,<:Card,<:Card,<:Card,<:Card,<:Card})
hand_ranks = map(cards -> (evaluate5(cards)..., Tuple(cards)), combinations(t, 5))
hand_ranks = map(combinations_6_choose_5(t)) do cards
(evaluate5(cards)..., cards)
end
i_max = argmin(map(x->x[1][1], hand_ranks))
return hand_ranks[i_max]
end
# Wrapper for 7 card hands:
function evaluate_full(t::Tuple{<:Card,<:Card,<:Card,<:Card,<:Card,<:Card,<:Card})
hand_ranks = map(cards -> (evaluate5(cards)..., Tuple(cards)), combinations(t, 5))
hand_ranks = map(combinations_7_choose_5(t)) do cards
(evaluate5(cards)..., cards)
end
i_max = argmin(map(x->x[1][1], hand_ranks))
return hand_ranks[i_max]
end
Expand All @@ -183,13 +234,17 @@ evaluate_compact(t::Tuple{<:Card,<:Card,<:Card,<:Card,<:Card}) = evaluate5(t)

# Wrapper for 6 card hands:
function evaluate_compact(t::Tuple{<:Card,<:Card,<:Card,<:Card,<:Card,<:Card})
hand_ranks = map(cards -> evaluate5(cards), combinations(t, 5))
hand_ranks = map(combinations_6_choose_5(t)) do cards
evaluate5(cards)
end
i_max = argmin(map(x->x[1], hand_ranks))
return hand_ranks[i_max]
end
# Wrapper for 7 card hands:
function evaluate_compact(t::Tuple{<:Card,<:Card,<:Card,<:Card,<:Card,<:Card,<:Card})
hand_ranks = map(cards -> evaluate5(cards), combinations(t, 5))
hand_ranks = map(combinations_7_choose_5(t)) do cards
evaluate5(cards)
end
i_max = argmin(map(x->x[1], hand_ranks))
return hand_ranks[i_max]
end
Expand Down
2 changes: 0 additions & 2 deletions src/evaluate5.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ using .HandCombinations
evaluate5(cards::Card...)
evaluate5(::Card,::Card,::Card,::Card,::Card)
evaluate5(::Tuple{Card,Card,Card,Card,Card})
evaluate5(::Vector{Card})
This is PokerHandEvaluator.jl's _core_ method.
Expand All @@ -24,7 +23,6 @@ for 5-card hands _only_.
function evaluate5 end

evaluate5(cards::Card...) = evaluate5(cards)
evaluate5(v::Vector) = evaluate5(Tuple(v))
# The product of 5 primes will be unique, and
# do not depend on the order, so we're using
# this to map card combinations to a single number
Expand Down
10 changes: 0 additions & 10 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ end
include("test_high_card.jl")
end

@testset "Vector interface" begin
@test first(evaluate5(A♠,K♠,Q♠,J♠,T♠)) == first(evaluate5([A♠,K♠,Q♠,J♠,T♠]))
end

@testset "N-methods" begin
N_offsuit = length(methods(PHE.evaluate5_offsuit))
N_flush = length(methods(PHE.evaluate5_flush))
Expand Down Expand Up @@ -95,20 +91,14 @@ end
che = CompactHandEval((A♠,2♠), table_cards)
fhe = FullHandEval((A♠,2♠)..., table_cards...)
che = CompactHandEval((A♠,2♠)..., table_cards...)
fhe = FullHandEval( collect((A♠,2♠, table_cards...)))
che = CompactHandEval( collect((A♠,2♠, table_cards...)))

fhe = FullHandEval((A♠,2♠), table_cards[1:end-1])
che = CompactHandEval((A♠,2♠), table_cards[1:end-1])
fhe = FullHandEval((A♠,2♠)..., table_cards[1:end-1]...)
che = CompactHandEval((A♠,2♠)..., table_cards[1:end-1]...)
fhe = FullHandEval( collect((A♠,2♠, table_cards[1:end-1]...)))
che = CompactHandEval( collect((A♠,2♠, table_cards[1:end-1]...)))

fhe = FullHandEval((A♠,2♠), table_cards[1:end-2])
che = CompactHandEval((A♠,2♠), table_cards[1:end-2])
fhe = FullHandEval((A♠,2♠)..., table_cards[1:end-2]...)
che = CompactHandEval((A♠,2♠)..., table_cards[1:end-2]...)
fhe = FullHandEval( collect((A♠,2♠, table_cards[1:end-2]...)))
che = CompactHandEval( collect((A♠,2♠, table_cards[1:end-2]...)))
end

2 comments on commit a3a06cf

@charleskawczynski
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/36869

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.1.1 -m "<description of version>" a3a06cf3513de457d9634f08b39ff86c451eb9f6
git push origin v0.1.1

Please sign in to comment.