Skip to content

Instantly share code, notes, and snippets.

@plonk
Last active December 21, 2015 10:28
Show Gist options
  • Select an option

  • Save plonk/6291703 to your computer and use it in GitHub Desktop.

Select an option

Save plonk/6291703 to your computer and use it in GitHub Desktop.
ポーカーの役を判定するやつ
# -*- coding: utf-8 -*-
# This is the Card class.
# An instance of it has a suit and value.
class Card
attr_reader :suit, :number
# Card numbers.
NUM_ACE = 14
NUM_JACK = 11
NUM_QUEEN = 12
NUM_KING = 13
SUITS = [:spade, :heart, :diamond, :club]
def initialize(suit, number)
# suit must be one of the following symbols.
raise ArumentError unless SUITS.include? suit
raise ArumentError unless number.is_a? Integer
@suit = suit
@number = number
end
def <=>(other)
self.number <=> other.number
end
include Comparable
end
class Hand
RANK_HIGH_CARD = 0
RANK_ONE_PAIR = 1
RANK_TWO_PAIRS = 2
RANK_THREE_OF_A_KIND = 3
RANK_STRAIGHT = 4
RANK_FLUSH = 5
RANK_FULL_HOUSE = 6
RANK_FOUR_OF_A_KIND = 7
RANK_STRAIGHT_FLUSH = 8
RANK_ROYAL_FLUSH = 9
SYMBOL_VALUE = {
'2'=>2,
'3'=>3,
'4'=>4,
'5'=>5,
'6'=>6,
'7'=>7,
'8'=>8,
'9'=>9,
'T'=>10,
'J'=>Card::NUM_JACK,
'Q'=>Card::NUM_QUEEN,
'K'=>Card::NUM_KING,
'A'=>Card::NUM_ACE,
'C'=>:club,
'D'=>:diamond,
'S'=>:spade,
'H'=>:heart
}
def initialize(cards)
@cards = []
cards.split(/ /).each do |mnemonic|
number = SYMBOL_VALUE[mnemonic[0]]
suit = SYMBOL_VALUE[mnemonic[1]]
@cards << Card.new(suit, number)
end
@cards.sort!
@cards.reverse!
@number = -1
end
attr_reader :number
def rank
{:royal_flush? => 9, :straight_flush? => 8, :four_of_a_kind? => 7, :full_house? => 6, :flush? => 5, :straight? => 4, :three_of_a_kind? => 3, :two_pairs? => 2, :one_pair? => 1, :high_card? => 0}.each_pair do |pred, n|
# p [pred, self.send(pred)]1
if self.send(pred)
return n
end
end
raise
end
def royal_flush?
return (flush? and straight? and
@cards.find {|c| c.number == 10} and
@cards.find {|c| c.number == Card::NUM_ACE})
end
def straight_flush?
return (straight? and flush?)
end
def four_of_a_kind?
return n_of_a_kind?(4)
end
def n_of_a_kind?(n)
@cards.each do |c|
if @cards.count {|d| d.number == c.number } == n
return true
end
end
return false
end
def full_house?
return (one_pair? and n_of_a_kind?(3))
end
def flush?
suits = @cards.map {|c| c.suit }
suits.all? {|s| s == suits.first}
end
def straight?
# p [:straight_cards, @cards]
a = @cards.map(&:number)
#p [:a, a]
b = a.each_cons(2)
# p [:b, b]
ret = b.map{|a, b| a - b}.all? {|n| n==1}
# p [:ret, ret]
ret
end
def three_of_a_kind?
n_of_a_kind?(3)
end
def two_pairs?
found = false
the_num = nil
@cards.each do |c|
if @cards.count {|d| d.number == c.number } == 2
the_num = c.number
found = true
break
end
end
return false unless found
cards = @cards.reject {|c| c.number == the_num }
cards.each do |c|
if @cards.count {|d| d.number == c.number } == 2
return true
end
end
return false
end
def one_pair?
n_of_a_kind?(2)
end
def high_card?
true
end
attr_reader :cards
def <=>(other)
res = self.rank <=> other.rank
return res unless res == 0
case self.rank
when RANK_FOUR_OF_A_KIND,
RANK_THREE_OF_A_KIND,
RANK_FULL_HOUSE,
RANK_TWO_PAIRS,
RANK_ONE_PAIR
res = same_hand_compare(other)
end
return res unless res == 0
res = high_card_compare(other)
raise "could not decide winner" if res == 0
return res
end
def max_value_of_largest_groups
values = self.cards.map{|c| c.number}.uniq
freqcounts = values.map {|n|
[ n, self.cards.count{|c| c.number == n} ]
}
maxfreq = freqcounts.map(&:last).max
return freqcounts.find_all { |val, freq| freq == maxfreq }.map(&:first).max
end
def same_hand_compare(other)
self.max_value_of_largest_groups <=> other.max_value_of_largest_groups
end
def high_card_compare(other)
res = nil
these = self.cards
those = other.cards
these.each_with_index do |this, i|
res = (this <=> those[i])
if res != 0
break
end
end
if res == 0
puts "Warning: high card comparison tied"
end
return res
end
include Comparable
end
def assert(bool)
raise unless bool
end
ranks = [:royal_flush?, :straight_flush?, :four_of_a_kind?, :full_house?, :flush?, :straight?, :three_of_a_kind?, :two_pairs?, :one_pair?, :high_card?].reverse
filename = ARGV[0] || "poker.txt"
=begin
# ------------ テスト ------------
highcard_ten = Hand.new( "TD 9D 6D 2D 3S" )
assert(highcard_ten.rank == Hand::RANK_HIGH_CARD)
one_pair_three = Hand.new( "TD 3D 6D 2D 3S" )
assert(one_pair_three.rank == Hand::RANK_ONE_PAIR)
two_pairs = Hand.new( "TD TS 3D 3S 2D")
assert(two_pairs.rank == Hand::RANK_TWO_PAIRS)
three_card = Hand.new("TD TS TH 3D 2D")
assert(three_card.rank == Hand::RANK_THREE_OF_A_KIND)
straight = Hand.new("TD 9S 8H 7D 6D")
assert(straight.rank == Hand::RANK_STRAIGHT)
flush = Hand.new("TD AD 3D 7D 9D")
assert(flush.rank == Hand::RANK_FLUSH)
full_house = Hand.new("TD TH TS 9D 9H")
assert(full_house.rank == Hand::RANK_FULL_HOUSE)
four_card = Hand.new("TD TH TS TC 9H")
assert(four_card.rank == Hand::RANK_FOUR_OF_A_KIND)
straight_flush = Hand.new("TD 9D 8D 7D 6D")
assert(straight_flush.rank == Hand::RANK_STRAIGHT_FLUSH)
royal_flush = Hand.new("AD KD QD JD TD")
assert(royal_flush.rank == Hand::RANK_ROYAL_FLUSH)
highcard_king = Hand.new( "KC 7H QC 6D 8H")
highcard_ace = Hand.new( "6S 5S AH 7S 8C")
p highcard_king.cards
p highcard_ace.cards
p (highcard_king <=> highcard_ace)
assert(highcard_king < highcard_ace)
puts " all tests succeeded"
=end
count = 0
File.open(filename) do |f|
f.each_line do |line|
line.chomp!
puts "----------------------"
p line[0,14]
p line[15,14]
player1_hand = Hand.new(line[0,14])
player2_hand = Hand.new(line[15,14])
p [:p1rank, ranks[ player1_hand.rank] ]
p [:p2rank, ranks[ player2_hand.rank] ]
if player1_hand == player2_hand
"TIED"
exit 1
end
p ((player1_hand > player2_hand) ? :player1 : :player2)
if player1_hand > player2_hand
count += 1
end
end
end
p count
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment