rpoker 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 837799d0168ceccf52c989c3b0c4133af13967d5
4
- data.tar.gz: 7f8c046ce3fe08e926c7f6000b1a77743f937dc3
3
+ metadata.gz: 59b9ef52714d62177bd664c67c4d2364d689a25c
4
+ data.tar.gz: 46884f0610f8cbb5bd184ca2b97a1ee8868ba21b
5
5
  SHA512:
6
- metadata.gz: 4d72492401a71f9802a157f5b11aea9ab91604cec64f0ff6d3ad631efa8e9df1453d6d29cd6d5c900e7f91b8aebd01d01fbc055b77cc83680faeb81d8bc82ea5
7
- data.tar.gz: 08f668889a8267825ea742a4e3aaa87d5d1dc5e4301318486a0412794c46b396d225299145c3173642d1169d6889ab46d79766ca8a399fa99f41d12244e86ce5
6
+ metadata.gz: 33a3401c1f6272b60b2f8dadc28af9f3ec26070ec67afc0500cdefd1d7f15dc7fa164d4a204670bad1c9f2f8f0b68cb4b6990520150e71a9e31c151b6be42996
7
+ data.tar.gz: 16e3413647dedf0457e538ed7aaef29066ae891706b92b11a769a0239cf95766a97e3c8d3f641207b2e5cfecf09c6dadcf62bb7c141392c7346f9c859fc78c10
data/lib/rpoker/card.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  class Card
2
2
  attr_reader :value, :suit
3
3
 
4
+ FACES = %w(T J Q K A)
5
+ SUITS = %w(h d c s)
6
+ VALUES = %w(2 3 4 5 6 7 8 9) + FACES
7
+
4
8
  FACE_VALUES = {
5
9
  "T" => 10,
6
10
  "J" => 11,
@@ -11,7 +15,10 @@ class Card
11
15
 
12
16
  def initialize(string)
13
17
  chars = string.split("")
18
+ raise ArgumentError.new("Too many characters") if chars.size > 2
19
+
14
20
  @value, @suit = [chars.first.upcase, chars.last.downcase]
21
+ validate!
15
22
  end
16
23
 
17
24
  def to_s
@@ -22,7 +29,14 @@ class Card
22
29
  value.to_i.to_s != value
23
30
  end
24
31
 
25
- def num_value
32
+ def to_i
26
33
  face_card? ? FACE_VALUES[value] : value.to_i
27
34
  end
35
+
36
+ private
37
+
38
+ def validate!
39
+ raise ArgumentError.new("The first character must be a card value") unless VALUES.include?(value)
40
+ raise ArgumentError.new("The second character must be a suit") unless SUITS.include?(suit)
41
+ end
28
42
  end
data/lib/rpoker/hand.rb CHANGED
@@ -20,7 +20,12 @@ class Hand
20
20
  cards.map { |card| card.is_a?(Card) ? card : Card.new(card) }
21
21
  when String
22
22
  cards.split(" ").map {|s| Card.new(s)}
23
+ else
24
+ raise ArgumentError.new("Input must be a string or array")
23
25
  end
26
+
27
+ validate!
28
+ sort_cards!
24
29
  end
25
30
 
26
31
  def <=>(other_hand)
@@ -31,7 +36,7 @@ class Hand
31
36
  end
32
37
 
33
38
  def display
34
- print cards.map { |card| card.to_s }.join(" ")
39
+ puts cards.join(" ")
35
40
  end
36
41
 
37
42
  def suits
@@ -42,39 +47,16 @@ class Hand
42
47
  @values ||= cards.map(&:value)
43
48
  end
44
49
 
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
50
+ def int_values
51
+ @int_values ||= cards.map(&:to_i)
65
52
  end
66
53
 
67
54
  def num_uniq_values
68
55
  @num_uniq_values ||= values.uniq.size
69
56
  end
70
57
 
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
58
  def wheel?
77
- sorted_values == [14, 5, 4, 3, 2]
59
+ values == %w(A 5 4 3 2)
78
60
  end
79
61
 
80
62
  def flush?
@@ -82,7 +64,7 @@ class Hand
82
64
  end
83
65
 
84
66
  def straight?
85
- wheel? || (sorted_values.first == sorted_values.last + 4 && num_uniq_values == 5)
67
+ wheel? || (int_values.first == int_values.last + 4 && num_uniq_values == 5)
86
68
  end
87
69
 
88
70
  def straight_flush?
@@ -90,26 +72,55 @@ class Hand
90
72
  end
91
73
 
92
74
  def full_house?
93
- same_values_in_sorted?(0, 2) && same_values_in_sorted?(3, 4)
75
+ same_values?(0, 2) && same_values?(3, 4)
94
76
  end
95
77
 
96
78
  def four_of_a_kind?
97
- same_values_in_sorted?(0, 3)
79
+ same_values?(0, 3)
98
80
  end
99
81
 
100
82
  def three_of_a_kind?
101
- same_values_in_sorted?(0, 2) && num_uniq_values == 3
83
+ same_values?(0, 2) && num_uniq_values == 3
102
84
  end
103
85
 
104
86
  def two_pair?
105
- same_values_in_sorted?(0, 1) && same_values_in_sorted?(2, 3) && num_uniq_values == 3
87
+ same_values?(0, 1) && same_values?(2, 3) && num_uniq_values == 3
106
88
  end
107
89
 
108
90
  def pair?
109
- same_values_in_sorted?(0, 1) && num_uniq_values == 4
91
+ same_values?(0, 1) && num_uniq_values == 4
110
92
  end
111
93
 
112
94
  def rank
113
95
  (TYPES.find { |type| send("#{type}?".to_sym) } || "high_card").gsub('_', ' ')
114
96
  end
97
+
98
+ private
99
+ # sort cards by their value multiplicity in descending order
100
+ # e.g. sort Js 2s Jh 4s 2c as Js Jh 2s 2c 4s
101
+ def sort_cards!
102
+ vals = cards.map(&:to_i)
103
+ counts = Hash[vals.map { |val| [val, vals.count(val)] }]
104
+ @cards.sort_by! { |card| [-counts[card.to_i], -card.to_i] }
105
+ end
106
+
107
+ def same_values?(start, stop)
108
+ vals = values[start..stop]
109
+ vals.all? { |value| value == vals.first }
110
+ end
111
+
112
+ def validate!
113
+ validate_length!
114
+ check_for_duplicates!
115
+ end
116
+
117
+ def validate_length!
118
+ raise ArgumentError.new("A hand must contain 5 cards") unless cards.size == 5
119
+ end
120
+
121
+ def check_for_duplicates!
122
+ unless cards.map(&:to_s).uniq.size == 5
123
+ raise ArgumentError.new("A hand cannot contain duplicate cards")
124
+ end
125
+ end
115
126
  end
@@ -22,16 +22,15 @@ class Matchup
22
22
 
23
23
  # both hands are high card rank and can be compared by
24
24
  # comparing values
25
- return same_type_winner
25
+ same_type_winner
26
26
  end
27
27
 
28
28
  private
29
29
  # for two hands of the same type (straight, flush, etc):
30
- # returns the winner by sorting the hands' numeric values
30
+ # returns the winner by sorting the hands' integer values
31
31
  # and then comparing value pairs in descending order
32
32
  def same_type_winner
33
-
34
- # check for the special case where one hand is a wheel
33
+ # check for the special case where either hand is a wheel
35
34
  if hand1.wheel? && hand2.wheel?
36
35
  return nil
37
36
  elsif hand1.wheel?
@@ -41,14 +40,14 @@ class Matchup
41
40
  end
42
41
 
43
42
  # compare the numeric value pairs
44
- values1, values2 = [hand1, hand2].map(&:uniq_values_sorted_by_count)
45
- values1.zip(values2).each do |v1, v2|
43
+ value_pairs = hand1.int_values.zip(hand2.int_values)
44
+ value_pairs.each do |v1, v2|
46
45
  if v1 > v2
47
46
  return hand1
48
47
  elsif v2 > v1
49
48
  return hand2
50
49
  end
51
50
  end
52
- return nil
51
+ nil
53
52
  end
54
53
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rpoker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Cornelis