I apologise for posting the URL incorrectly. It's really:
http://www.dave.burt.id.au/ruby/poker.rb
This is a pretty long project. Here are some highlights:
# each hand type has a name and a function taking a hand and returning it,
# sorted, or nil if the hand doesn't match this type.
HandTypes = [
['Royal Flush', proc {|hand|
if hand.find_all{|c|c.value >= 10}.map(:suit).frequencies(5).size >= 1
Poker.find_straight(hand)
end }],
['Straight Flush', proc {|hand|
suit, count = *hand.map(:suit).frequencies(5)[0]
if count && count >= 1
if straight = Poker.find_straight(hand.find_all {|card| card.suit ==
suit })
result = hand.dup
result.delete_if {|card| straight.include?(card) }
straight + result.sort_by_most_frequent(:value)
end
end }],
['Four of a Kind', proc {|hand|
if hand.map(:value).frequencies(2).size >= 4
hand.sort_by_most_frequent :value
end }],
['Flush', proc {|hand|
if hand.map(:suit).frequencies(5).size >= 1
hand.sort_by_most_frequent :suit
end }],
['Straight', proc {|hand|
Poker.find_straight(hand) }],
['Three of a Kind', proc {|hand|
if hand.map(:value).frequencies(3).size >= 1
hand.sort_by_most_frequent :value
end }],
['Two Pair', proc {|hand|
if hand.map(:value).frequencies(2).size >= 2
hand.sort_by_most_frequent :value
end }],
['Pair', proc {|hand|
if hand.map(:value).frequencies(2).size >= 1
hand.sort_by_most_frequent :value
end }],
['High Card', proc {|hand|
hand.sort.reverse }]
]
#
# Returns [n, "Hand type", ordered_cards]
# The n at the front is bigger for better hands, so that
# you can sort by hand_value.
#
def self.hand_value(cards, min_cards = 7) # self #=> Poker:Module
if cards.size >= min_cards
HandTypes.each_with_index do |hand_type, index|
hand_match = hand_type[1].call(cards)
if hand_match
# return EvaluatedHand.new(hand_match, hand_type[0], [HandTypes.size -
index, hand_match])
return [
HandTypes.size - index,
hand_type[0],
hand_match
]
end
end
end
[0, '', cards.sort_by_most_frequent(:value)]
end
# then it all comes together like this:
hands = []
# get hands from input and evaluate them
input.each do |line|
hands << line.to_cards.poker_value
end
# determine the winner
winner = hands.inject([]) do |memo, hand|
[memo, hand].max
end
# output each hand and its value
hands.each do |hand|
puts "#{hand[2]} #{hand[1]} #{'(winner)' if hand == winner}"
end
That plus a Poker::find_straight and Array#frequencies and that's pretty
much all there is to my answer.
Cheers,
Dave
"Dave Burt" <dave / burt.id.au> faked:
> http://www.dave.burt.id.au/poker.rb
>
> (requires card.rb in the same directory)
>
> An explanation (and comments) will come later tonight.
>
> Cheers,
> Dave