Poker hand analyser: Difference between revisions

Content deleted Content added
m {{out}} / Category:Cards
→‎{{header|Ruby}}: change rank symbol
Line 1,616:
attr_accessor :ordinal
attr_reader :suit, :face
 
SUITS = %i(♥ ♦ ♣ ♠)
FACES = %i(2 3 4 5 6 7 8 9 10 j q k a)
Line 1,624:
@ordinal = FACES.index(@face)
end
 
def <=> (other) #used for sorting
self.ordinal <=> other.ordinal
end
 
def to_s
["#@face, #@suit].join"
end
 
private
def parse(str)
face, suit = str.chop.to_sym, str[-1].to_sym
raise ArgumentError, "invalid card: #{str}" unless FACES.include?(face) && SUITS.include?(suit)
[face, suit]
end
 
end
 
class Hand
include Comparable
attr_reader :cards, :rank
 
RANKS = %i(high_cardhigh-card one_pairone-pair two_pairtwo-pair three_of_a_kindthree-of-a-kind straight flush
flushfull-house full_housefour-of-a-kind four_of_a_kind straight_flushstraight-flush five_of_a_kindfive-of-a-kind)
WHEEL_FACES = %i(2 3 4 5 a)
def initialize(str_of_cards)
@cards = str_of_cards.downcase.splittr(/[\s+|',|',' ]/').split.map{|str| Card.new(str)}
grouped = @cards.group_by(&:face).values
@tiebreaker = grouped.sort_by {|ar| [ar.size, ar.first]}.reverse
@face_pattern = grouped.map(&:size).sort
@rank = categorize
@rank_num = RANKS.index(@rank)
@tiebreaker = grouped.sort_by map{|ar| [ar.size, ar.first.ordinal]}.sort.reverse
end
 
def category
@rank.to_s.tr("_", "-")
end
 
def <=> (other) # used for sorting and comparing
self.compare_value <=> other.compare_value
end
 
def to_s
@cards.map(&:to_s).join(" ")
end
 
protected # accessible for Hands
def compare_value
[@rank_num, @tiebreaker]
end
 
private
def one_suit?
@cards.map(&:suit).uniq.size == 1
end
 
def consecutive?
sort.each_cons(2).all? {|c1,c2| c2.ordinal - c1.ordinal == 1 }
end
 
def sort
if @cards.sort.map(&:face) == WHEEL_FACES then
@cards.detect {|c| c.face == :a}.ordinal = -1
end
Line 1,693 ⟶ 1,688:
def categorize
if consecutive?
rank = :flush if one_suit?
rank = one_suit? ? :'straight-flush' : if consecutive? :straight
rank = :straight_flush if rank == :straight andelsif one_suit?
return rank if rank:flush
else
return case @face_pattern
when [1,1,1,1,1] then :high_card
when [1,1,1,21,1] then :one_pair'high-card'
when [1,21,1,2] then :two_pair'one-pair'
when [1,12,32] then :three_of_a_kind'two-pair'
when [21,1,3] then :full_house'three-of-a-kind'
when [12,43] then :four_of_a_kind'full-house'
when [51,4] then :five_of_a_kind'four-of-a-kind'
when [5] then :'five-of-a-kind'
end
end
end
 
end
 
# Demo
test_hands = <<EOS
"2♥ 2♦ 2♣ k♣ q♦
2♥ 5♥ 7♦ 8♣ 9♠
a♥ 2♦ 3♣ 4♣ 5♦
Line 1,725 ⟶ 1,721:
9♥ 10♥ q♥ k♥ j♣
2♥ 3♥ 4♥ 5♥ a♥
2♥ 2♥ 2♦ 3♣ 3♦"
EOS
 
hands = test_hands.each_line.map{|line| Hand.new(line) }
puts "High to low"
hands.sort.reverse.each{|hand| puts "#{hand}\t #{hand.categoryrank}" }
puts
 
str = <<EOS
str = "joker 2♦ 2♠ k♠ q♦
joker 5♥2♦ 7♦2♠ 8♠k♠ 9♦q♦
joker 2♦5♥ 3♠7♦ 4♠8♠ 5♠9♦
joker 3♥2♦ 2♦3♠ 3♠4♠ 3♦5♠
joker 7♥3♥ 2♦ 3♠ 3♦
joker 7♥ 7♦2♦ 7♠3♠ 7♣3♦
joker j♥7♥ q♥7♦ k♥7♠ A♥7♣
joker j♥ q♥ k♥ A♥
joker 4♣ k♣ 5♦ 10♠
joker joker4♣ k♣ 7♣5♦ 6♣ 4♣10♠
joker 2♦k♣ joker7♣ 4♠6♣ 5♠4♣
joker 2♦ joker Q♦ joker 4♠ A♠ 10♠5♠
joker Q♦ joker A♦A♠ 10♦10♠
joker Q♦ joker 2♦ 2♠ joker A♦ q♦"10♦
str = "joker 2♦ 2♠ k♠joker q♦
EOS
 
# Neither the Card nor the Hand class supports jokers
Line 1,755 ⟶ 1,754:
all_tries = cards_in_arrays.shift.product(*cards_in_arrays).map{|ar| Hand.new(ar.join" ")} #calculate the Whatshisname product
best = all_tries.max
puts "#{line.strip}: #{best.categoryrank}"
end</lang>
 
</lang>
{{out}}
<pre>
Line 1,790 ⟶ 1,789:
joker 2♦ 2♠ joker q♦: four-of-a-kind
</pre>
 
=={{header|Tcl}}==
{{works with|Tcl|8.6}}