Reputation: 2103
My question is very similar to "How do I return a group of sequential numbers that might exist in an array?".
I need to find a way to check if a given array of numbers (card values basically) is a poker straight, or simply return the longest sequence.
As Mr. Thomas suggested, each_cons
works well, but in Texas Holdem, straight is not only 2, 3, 4, 5, 6 or 8, 9, 10, J, Q, but K, A, 2, 3, 4 also.
If we have figures signed as numbers I think it will make everything easier: J will be 11, Q will be 12 and so on.
Any idea how to achieve this?
Upvotes: 0
Views: 836
Reputation: 80075
Just enumerate all possible straights:
All_Poker_Straights = %w(A 2 3 4 5 6 7 8 9 10 J Q K A).each_cons(5)
and check if the (sorted) hand is one of them:
p All_Poker_Straights.include?(%w(4 5 6 7 8))
# => true
Upvotes: 1
Reputation: 168199
class Array
def sequences
a = sort.uniq.inject([]){|a, e|
a.last && e == a.last.last + 1 ? a.last.push(e) : a.push([e])
a
}
a.push([*a.pop, *a.shift]) if a.first.first == 1 && a.last.last == 13
a
end
end
[1, 3, 4].sequences # => [[1], [3, 4]]
[1, 3, 4, 2, 5].sequences # => [[1, 2, 3, 4, 5]]
[1, 10, 12, 11, 13].sequences # => [[10, 11, 12, 13, 1]]
[1, 3, 4].sequences.max{|a| a.length} # => [3, 4]
[1, 3, 4, 2, 5].sequences.max{|a| a.length} # => [1, 2, 3, 4, 5]
[1, 10, 12, 11, 13].sequences.max{|a| a.length} # => [10, 11, 12, 13, 1]
Upvotes: 0
Reputation: 55002
Maybe it's not optimal but I would use Array#rotate!
:
@values = %w{A 2 3 4 5 6 7 8 9 10 J Q K A}
def longest_sequence cards
cards, values = cards.sort_by{|c| @values.index c}, @values.dup
# iterate down from 5 and rotate through cards/values until you find a match
5.downto(1).each do |n|
values.length.times do
cards.length.times do
return cards[0...n] if cards[0...n] == values[0...n]
cards.rotate!
end
values.rotate!
end
end
end
longest_sequence ['A', '3', '4']
#=> ["3", "4"]
longest_sequence ['A', '3', '4', '2', '5']
#=> ["A", "2", "3", "4", "5"]
longest_sequence ['A', '10', 'Q', 'J', 'K']
#=> ["10", "J", "Q", "K", "A"]
Upvotes: 1
Reputation: 29599
try this (assuming you've replaced the cards with numbers, A=1, 2=2)
def straight?(my_cards)
sorted = my_cards.uniq.sort
if sorted.length < 5
# cant form a straight with duplicates
false
else
# also give an Ace a value of 14 so it can be placed after a King
sorted << 14 if sorted[0] == 1
# returns true if the last number is equal to 4 plus the first so
# a hand with 2,3,4,5,6 will return true
sorted.first + 4 == sorted.last
end
Upvotes: 1
Reputation: 509
Your input is an array of numbers. so I am assuming that J = 11, Q = 12, K= 13 and A= 1.
1) Sort the array 2) iterate through the array and the moment you run into the next number being more than one number greater than the previous number return false since it is not a straight hand.
if you are not assuming that J=11, Q=12, K=13, A=1, then you need an additional data structure (Perhaps a dictionary to make complexity low since a lookup is a O(1)) time. Dictionary a = new Dictionary(); a.key = "K"; a.value = "13".
now if you have an array of [10,11,J,Q,K] => iterate thourgh it and do a look up in your dictionary, and once your value is one more greater than the previous card then return false..
OBviously you'll have base cases, in case the input array is more than length 5. or is empty or is < 5. If you are doing overlapping straights, then the only thing that can come after a K is a A with value 1, so if thats the case then continue on in your loop. Hopefully this helps.
Good luck.
Upvotes: 1