Skip to content

Instantly share code, notes, and snippets.

@rferraz
Created June 29, 2011 23:20
Show Gist options
  • Save rferraz/1055255 to your computer and use it in GitHub Desktop.
Save rferraz/1055255 to your computer and use it in GitHub Desktop.
Poker Hands
class Card
attr_reader :value, :suit
def self.parse(str)
if str =~ /^([2-9AJQK])([CDHS])$/
self.new($1, $2)
end
end
def initialize(value, suit)
@value, @suit = value.to_i, suit
end
def to_s
"#{value}#{suit}"
end
end
def Card(str)
Card.parse(str)
end
class Hand
include Enumerable
def initialize(c1, c2, c3, c4, c5)
@cards = [c1, c2, c3, c4, c5].sort_by { |c| c.value }
end
def each(&block)
@cards.each(&block)
end
end
class HandDetector
@@strategies = []
def self.strategy(klass)
@@strategies << klass
end
def self.detect(hand)
self.new(hand).detect
end
def initialize(hand)
@hand = hand
end
def detect
rank = nil
@@strategies.each do |klass|
rank = klass.new(@hand).run
break if rank
end
rank
end
end
module Strategies
class Base
def self.inherited(subklass)
HandDetector.strategy(subklass)
end
def initialize(hand)
@hand = hand
end
def each_repetition(n)
last_card = nil
repeat_count = 1
@hand.each do |card|
if last_card && last_card.value == card.value
repeat_count += 1
yield card if repeat_count == n
else
repeat_count = 1
end
last_card = card
end
false
end
end
class Straight < Base
def run
offset = -1
first_value = @hand.first.value
:straight if @hand.all? do |card|
offset += 1
card.value == first_value + offset
end
end
end
class ThreeOfAKind < Base
def run
each_repetition(3) do |card|
return :three_of_a_kind
end
end
end
class TwoPairs < Base
def run
count = 0
each_repetition(2) do |card|
count += 1
end
return :two_pairs if count == 2
end
end
class Pair < Base
def run
each_repetition(2) do |card|
return :pair
end
end
end
class HighCard < Base
def run
:high_card
end
end
end
require 'test/unit'
class PokerTestCase < Test::Unit::TestCase
def detect_hand(str)
cards = str.split(/\s/).map { |cs| Card(cs) }
HandDetector.detect Hand.new(*cards)
end
def test_that_is_high_card
assert_equal :high_card, detect_hand("2H 3D 5S 9C KD")
end
def test_that_is_pair
assert_equal :pair, detect_hand("2H 3D 5S KC KD")
end
def test_that_is_two_pairs
assert_equal :two_pairs, detect_hand("2H 5D 5S KC KD")
end
def test_that_is_three_of_a_kind
assert_equal :three_of_a_kind, detect_hand("2H 3D KS KC KD")
end
def test_that_is_straight
assert_equal :straight, detect_hand("2H 3D 4S 5C 6D")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment