Leo
Leo

Reputation: 2103

Checking array of numbers for a Poker straight?

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

Answers (5)

steenslag
steenslag

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

sawa
sawa

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

pguardiario
pguardiario

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

jvnill
jvnill

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

nav
nav

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

Related Questions