Got more questions? Find advice on: ASP | SQL | XML | Windows
in Search
Welcome to RegexAdvice Sign in | Join | Help

Michael Ash's Regex Blog

Regex Musings

Shuffle up and deal

I thought I’d have a little fun and see if I could write a (or some) regexps to find winning poker hands. I stumbled a little bit but did finally get all the hands. First off let me state these solutions aren’t perfect. They make two assumptions. First that the cards are sorted, from low rank to high. Second it is a five card hand. Against 7 cards these will fail on occasion. First off for the non-poker aware here are the winning poker hands from lowest to highest.

 Spades = S = ♠ Clubs = C =♣ Hearts = H = ♥ Diamonds = D =♦

I don’t know if the characters for the card suits will show on this web page so I’ll use letters in the samples

1) Highest single card. Ace is the highest, deuce (2) is the lowest. If two or more players have the same highest card the next highest card breaks the tie. The High card also break ties of stronger hands if two or more play have equal hands. The highest cards making up a stronger hand break ties of the same type, but not equal of stronger hands

2) A pair: Two card of exactly the same rank. Two 2’s OR Two Aces. The highest ranked card of the paired cards break the tie.

3) Two Pair: Two different pairs. Two 2’s AND Two Aces. The highest ranked card of the paired cards break the tie. The fifth card is the final tiebreaker

4) Three of a Kind: Three card of exactly the same rank. Three 2’s. The Highest ranked 3 of a kind breaks ties

5) Straight: 5 cards of consecutive rank but not the same suit. 2,3,4,5,6. Also an Ace can be the lowest rank forming a 5 high straight (wheel) A,2,3,4,5 or Ace can be high forming an Ace high straight 10,J,Q,K,A. High card breaks ties

6) Flush: Five cards of the same suit. All five are not of consecutive rank. 2H,4H,6H,8H,JH. High card breaks ties

7) Full House: Three of a Kind of one rank AND a pair of another. The rank of the three of kind cards are used as the high card for tiebreakers.

8) Four of Kind. All 4 card of the same rank. The rank of these cards break ties

9) Straight Flush - five cards of consecutive rank and the same suit. 2S,3S,4S,5S,6S . High card breaks ties. A Royal Straight Flush is the highest possible straight flush, and highest possible non-wildcard poker hand, 10D,JD,QD,KD,AD

Now for the regexps. Note these only find the hands but doesn’t determine the high card or what beats what.

1) High Card – N/A

2) ([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\1(?!\2)([\u2660\u2663\u2665\u2666]) #pair

3) ([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\1(?!\2)([\u2660\u2663\u2665\u2666])(?:(?!\1)(?:[2-9JQKA]|10)(?:[\u2660\u2663\u2665\u2666]))?(?!\1)([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\4(?!\5)([\u2660\u2663\u2665\u2666]) # two pair

4) ([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\1(?!\2)([\u2660\u2663\u2665\u2666])\1(?!\2|\3)([\u2660\u2663\u2665\u2666]) #3 of a kind

5) (?=(2.3.4.5 A|2.3.4.5.6|3.4.5.6.7|4.5.6.7.8|5.6.7.8.9|6.7.8.9.10.|7.8.9.10.J.|8.9.10.J.Q.|9.10.J.Q.K.|10.J.Q.K.A.))(?:([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])){5} # Straight ?

6) ([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])(?!\1)([2-9JQKA]|10)\2(?!\1\3)([2-9JQKA]|10)\2(?!\1\3\4)([2-9JQKA]|10)\2(?!\1\3\4\5)([2-9JQKA]|10)\2 #Flush

7) ([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\1(?!\2)([\u2660\u2663\u2665\u2666])(?:(?:\1(?!\2|\3)(?:[\u2660\u2663\u2665\u2666])(?!\1)([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\5(?!\2)([\u2660\u2663\u2665\u2666]))|(?:(?!\1)([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\1(?!\2)([\u2660\u2663\u2665\u2666])\1(?!\2|\3)([\u2660\u2663\u2665\u2666])) # Full House

8) ([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\1(?!\2)([\u2660\u2663\u2665\u2666])\1(?!\2|\3)([\u2660\u2663\u2665\u2666])\1(?!\2|\3|\4)([\u2660\u2663\u2665\u2666]) #4 of a kind

9) (?=(?:.2.3.4.5|2.3.4.5.6|3.4.5.6.7|4.5.6.7.8|5.6.7.8.9|6.7.8.9.10.|7.8.9.10.J.|8.9.10.J.Q.|9.10.J.Q.K.|10.J.Q.K.A.))([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])(?!\1)([2-9JQKA]|10)\2(?!\1\3)([2-9JQKA]|10)\2(?!\1\3\4)([2-9JQKA]|10)\2(?!\1\3\4\5)([2-9JQKA]|10)\2 # Straight Flush

The character class [2-9JQKA] are the rank of all the cards except the Ten. The rank expressions is ([2-9JQKA]|10) The expression ([\u2660\u2663\u2665\u2666]) are the Unicode characters that are the dark shaded card suits Spades, Clubs, Hearts and diamonds respectively . (2661,2662,2664, 2667 are the light colored suit) If you don’t have the correct fonts to view these characters you can use [SCHD]

The reasons these all won’t work with seven cards, some do, is because the expression are looking for one card right next to the other. In most cases this isn’t a problem when they are sorted but in certain cases a valid winning hand won’t be found.

Case 1) Two Pair. The above express will match 22566 but not 2234588. This one has a simple fix

 ([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\1(?!\2)([\u2660\u2663\u2665\u2666])(?:(?!\1)(?:[2-9JQKA]|10)(?:[\u2660\u2663\u2665\u2666])){0,3}(?!\1)([2-9JQKA]|10)([\u2660\u2663\u2665\u2666])\4(?!\5)([\u2660\u2663\u2665\u2666]) # two pair

The difference between this and the to original, this one allows 0 to 3 card that are not part of the first pair to be between to two pairs.

Case 2) Straight: As long as your straight is your first 5, last 5 cards or cards 2-6. The above regex will work fine but a case like 234456J will fail but is a straight. Why? The second 4 causes the expression to fail but the hand does contain 5 cards of consecutive rank (23456) . The problem arises if you have a pair, two pair or three of a kind made up of the interior portion of your straight. The workaround is to compare the regex with multiple variations of the hand. There are only 23 not including the ones the original will match. Cards 13456, 14567, 13567, 13467, 13457, 12456, 12567, 12467, 12457, 12456, 12356, 12367, 12357, 12346, 12347, 12367, 12357, 12347, 12346, 24567, 23567, 23467, 23457

Case 3) Flush. Same problem and solution as a straight.

Case 4) Full House same as two pair

Case5) Straight Flush Same as 2 and 3

This was simply a mental exercise but if you see any improvements or errors on the regexps let me know.

Published Thursday, May 27, 2004 5:05 PM by mash

Comments

 

mash said:

I can offer up some suggestions. The following code will match a straight of 2-6, but not care about the order of the digits.

^([2-6])(?!.*\1)([2-6])(?!.*\2)([2-6])(?!.*\3)([2-6])(?!.*\4)([2-6])$

This results in a much larger straight expression, and it is not 7 card aware. You'd have to insert dots to get over your suits. I find this pretty interesting, I may have to take a harder look at some later point in time.
May 27, 2004 7:17 PM
 

mash said:

Justin I like that regex. I follow your thinking because also I have have a regex http://www.regexlib.com/REDetails.aspx?regexp_id=564 that does pretty much the same thing. I had thought about using a variation it to do what you did but realized that I'd need to repeat that pattern for every varaition 2-6, 3-7, 4-8 and so on. So you don't get away from the alternation and keeping up with all the backreferences get hairier. Like you said the final expression becomes much longer
May 27, 2004 11:32 PM
 

TrackBack said:

Michael Ash ger sig i sin Regex Blog p att skapa ett reguljrt uttryck fr vinnande pokerhnder. Kul sak. Se vidare anteckningen Shuffle up and deal. Liksom en av kommentatorerna kommer ven jag att fundera lite p detta... Se ven...
May 28, 2004 11:55 AM
Anonymous comments are disabled