rpoker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 14c1fe8bbdb62e78f7cf12668b8c4c96392fb18c
4
+ data.tar.gz: c09fbd0fa370841e8fa10bb54308b5f1a6e0975f
5
+ SHA512:
6
+ metadata.gz: 1804d821324d68dec6fcc5604991244505bf18dbb1120cdbae2c585df6b1f9b99c9d8926aa24d2ee8ceb4a2a2a11ae9be0ad3f667a86b06a19274d1f5ef23d34
7
+ data.tar.gz: 92bec40a278e09dc0916ceb590bda945f9921e61c75551c036033db9a6334297685bc2e950fc317bc39fb632553dfe85c3a91a0b0645383c4340d865fd215a98
@@ -0,0 +1,28 @@
1
+ class Card
2
+ attr_reader :value, :suit
3
+
4
+ FACE_VALUES = {
5
+ "T" => 10,
6
+ "J" => 11,
7
+ "Q" => 12,
8
+ "K" => 13,
9
+ "A" => 14
10
+ }
11
+
12
+ def initialize(string)
13
+ chars = string.split("")
14
+ @value, @suit = [chars.first.upcase, chars.last.downcase]
15
+ end
16
+
17
+ def to_s
18
+ "#{@value}#{@suit}"
19
+ end
20
+
21
+ def face_card?
22
+ value.to_i.to_s != value
23
+ end
24
+
25
+ def num_value
26
+ face_card? ? FACE_VALUES[value] : value.to_i
27
+ end
28
+ end
@@ -0,0 +1,115 @@
1
+ class Hand
2
+ include Comparable
3
+ attr_reader :cards
4
+
5
+ TYPES = %w(
6
+ straight_flush
7
+ four_of_a_kind
8
+ full_house
9
+ flush
10
+ straight
11
+ three_of_a_kind
12
+ two_pair
13
+ pair
14
+ )
15
+
16
+ def initialize(cards)
17
+ @cards =
18
+ case cards
19
+ when Array
20
+ cards.map { |card| card.is_a?(Card) ? card : Card.new(card) }
21
+ when String
22
+ cards.split(" ").map {|s| Card.new(s)}
23
+ end
24
+ end
25
+
26
+ def <=>(other_hand)
27
+ winner = Matchup.new(self, other_hand).winner
28
+ return 1 if winner == self
29
+ return 0 if winner == nil
30
+ return -1 if winner == other_hand
31
+ end
32
+
33
+ def display
34
+ print cards.map { |card| card.to_s }.join(" ")
35
+ end
36
+
37
+ def suits
38
+ @suits ||= cards.map(&:suit)
39
+ end
40
+
41
+ def values
42
+ @values ||= cards.map(&:value)
43
+ end
44
+
45
+ def num_values
46
+ @num_values ||= cards.map(&:num_value)
47
+ end
48
+
49
+ def sorted_values
50
+ @sorted_values ||= num_values.sort.reverse
51
+ end
52
+
53
+ # sort card values by their multiplicity in descending order
54
+ # e.g. for the hand Js 2s Jh 4s 2c the method returns [11, 11, 2, 2, 4]
55
+ def values_sorted_by_count
56
+ @values_sorted_by_count ||=
57
+ [4,3,2,1].inject([]) { |sorted, n|
58
+ sorted += sorted_values.select { |value| sorted_values.count(value) == n } }
59
+ end
60
+
61
+ # sort distinct card values by their multiplicity in descending order
62
+ # e.g. for the hand Js 2s Jh 4s 2c the method returns [11, 2, 4]
63
+ def uniq_values_sorted_by_count
64
+ @uniq_values_sorted_by_count ||= values_sorted_by_count.uniq
65
+ end
66
+
67
+ def num_uniq_values
68
+ @num_uniq_values ||= values.uniq.size
69
+ end
70
+
71
+ def same_values_in_sorted?(start, stop)
72
+ values_slice = values_sorted_by_count[start..stop]
73
+ values_slice.all? { |value| value == values_slice.first }
74
+ end
75
+
76
+ def wheel?
77
+ sorted_values == [14, 5, 4, 3, 2]
78
+ end
79
+
80
+ def flush?
81
+ suits.all? { |suit| suit == suits.first }
82
+ end
83
+
84
+ def straight?
85
+ wheel? || (sorted_values.first == sorted_values.last + 4 && num_uniq_values == 5)
86
+ end
87
+
88
+ def straight_flush?
89
+ flush? && straight?
90
+ end
91
+
92
+ def full_house?
93
+ same_values_in_sorted?(0, 2) && same_values_in_sorted?(3, 4)
94
+ end
95
+
96
+ def four_of_a_kind?
97
+ same_values_in_sorted?(0, 3)
98
+ end
99
+
100
+ def three_of_a_kind?
101
+ same_values_in_sorted?(0, 2) && num_uniq_values == 3
102
+ end
103
+
104
+ def two_pair?
105
+ same_values_in_sorted?(0, 1) && same_values_in_sorted?(2, 3) && num_uniq_values == 3
106
+ end
107
+
108
+ def pair?
109
+ same_values_in_sorted?(0, 1) && num_uniq_values == 4
110
+ end
111
+
112
+ def rank
113
+ (TYPES.find { |type| send("#{type}?".to_sym) } || "high_card").gsub('_', ' ')
114
+ end
115
+ end
@@ -0,0 +1,54 @@
1
+ class Matchup
2
+ attr_reader :hand1, :hand2
3
+
4
+ def initialize(hand1, hand2)
5
+ @hand1, @hand2 = hand1, hand2
6
+ end
7
+
8
+ def winner
9
+ Hand::TYPES.each do |type|
10
+ # build the boolean type check method
11
+ is_type = "#{type}?".to_sym
12
+
13
+ # check whether either hand is of the type
14
+ if hand1.send(is_type) && hand2.send(is_type)
15
+ return same_type_winner
16
+ elsif hand1.send(is_type)
17
+ return hand1
18
+ elsif hand2.send(is_type)
19
+ return hand2
20
+ end
21
+ end
22
+
23
+ # both hands are high card rank and can be compared by
24
+ # comparing values
25
+ return same_type_winner
26
+ end
27
+
28
+ private
29
+ # for two hands of the same type (straight, flush, etc):
30
+ # returns the winner by sorting the hands' numeric values
31
+ # and then comparing value pairs in descending order
32
+ def same_type_winner
33
+
34
+ # check for the special case where one hand is a wheel
35
+ if hand1.wheel? && hand2.wheel?
36
+ return nil
37
+ elsif hand1.wheel?
38
+ return hand1
39
+ elsif hand2.wheel?
40
+ return hand2
41
+ end
42
+
43
+ # compare the numeric value pairs
44
+ values1, values2 = [hand1, hand2].map(&:uniq_values_sorted_by_count)
45
+ values1.zip(values2).each do |v1, v2|
46
+ if v1 > v2
47
+ return hand1
48
+ elsif v2 > v1
49
+ return hand2
50
+ end
51
+ end
52
+ return nil
53
+ end
54
+ end
data/lib/rpoker.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "rpoker/hand"
2
+ require "rpoker/card"
3
+ require "rpoker/matchup"
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rpoker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Cornelis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-17 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email: bencornelis02@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/rpoker.rb
20
+ - lib/rpoker/card.rb
21
+ - lib/rpoker/hand.rb
22
+ - lib/rpoker/matchup.rb
23
+ homepage: http://rubygems.org/gems/rpoker
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.4.8
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: Ruby library for comparing and ranking poker hands
47
+ test_files: []
48
+ has_rdoc: