|
|
Sat, Apr. 28th, 2007, 12:56 pm Flush vs. Straight

As every poker player knows, the chances of a random set of five cards being a flush is less than the chances of it being a straight. So, if you deal out one card face-up at a time until either five of the dealt cards form a straight or five of the dealt cards form a flush, which is more likely to happen first, a flush or a straight? The obvious answer is a straight, because that's the more likely hand, but that might not be correct. To see why, consider this question: If you've dealt out seventeen cards, what are the chances that you've dealt a flush? My exercise for you, the reader, is to figure out the chances that a flush versus a straight will come up first (both coming up at once should be considered a tie). If it turns out that flushes are in fact more likely to come up first, this might make a very good sucker bet. Update: Some commenters ran simulations, and the margin for flush is quite solid (about 60:40, not counting ties). This leads to a great hustle: show up to a poker game and make the repeated asinine assertion that flushes are more likely than straights even though flushes beat straights. When someone finally gets fuming mad at you in disagreement, suggest this bet as a way to settle the score. Update2: There was a bug in the code, and the odds are actually about 51/39/10, which is still a solid edge.
Sat, Apr. 28th, 2007 08:32 pm (UTC)
steeltoe

There are 5108 possible ways to make a five card flush. There are 10200 possible ways to make a five card straight. What am I missing?
Sat, Apr. 28th, 2007 08:33 pm (UTC)
steeltoe

I should say, out of all of the possible 2598960 possible 5 card combinations.
Sat, Apr. 28th, 2007 08:41 pm (UTC)
steeltoe

I think I see what you are getting at - if after drawing five cards, you don't have the hand you are looking for, but you have 4 of the five cards, an open ended straight will require 1 of 8 out of 47 possible cards to complete the hand. A flush will require 1 of 9 out of 47 possible cards to complete. While the flush will be more probable after 4 cards, getting those first four is more difficult.
Sat, Apr. 28th, 2007 08:55 pm (UTC)
bramcohen

The first exercise explains the concept - if you've dealt out 17 cards, what is the probability that five of them form a flush? Once you've worked that out, it should be easy to compare to the probability that five of those 17 cards form a straight.
Sat, Apr. 28th, 2007 09:00 pm (UTC)
steeltoe

Ah I see - the sucker bet in here assumes one has seen a certain number of cards without a flush. The sucker will assume that because a flush is rarer, that it's more likely they will see a straight first. But we've only made the bet after we've made it over the hump of the first four cards. I'm coding now - a fine puzzle you've set up.
Sat, Apr. 28th, 2007 09:03 pm (UTC)
bramcohen

I'm not sure what you're saying. I'm proposing a bet which is made before any cards have been dealt, and ends when the first straight or flush, using any subset of five of the available cards, has been reached. I think this *might* be favorable to flushes happening first, although calculating that rigorously looks a bit difficult (monte carlo methods should be straightforward though).
Sat, Apr. 28th, 2007 10:12 pm (UTC)
steeltoe

The calculations of this are very similar to figuring out 7 card stud hands which is 5 cards of 7 out of 52. Because of the difference between 17 and 5 is so much larger than 7 and 5, it makes it more difficult. Interesting things happen when you get to 17 cards - You have to have at least one pair, for instance, and you *must* have at least a five card flush. I understand the original problem better now, and if I had more formal mathematical training, I would be able to explain this a little better.
Sun, Apr. 29th, 2007 12:27 am (UTC)
dossy

P(flush | no flush yet) vs. P(straight | no straight yet)? N = cards dealt so far, where N = [4, 17]. Hey, wait a minute ... the 17th card *must* always complete a flush. :-P I'm a sucker.
Sun, Apr. 29th, 2007 12:50 am (UTC)
dossy

To complete the thought, the question becomes: how many permutations of 16 cards exist such that no 5-card straight appears? My combinatorics skills are too weak to solve this.
Sun, Apr. 29th, 2007 02:13 am (UTC)
bramcohen

The exact probability of there being a straight among 17 cards is very difficult to compute, but I can assure you that it's less than 100%. The simplest way to approach this problem is to use monte carlo methods, that is, run the experiment a million times and see which side wins more.
Sun, Apr. 29th, 2007 02:29 am (UTC)
dossy

Just to make sure my combinatorics hasn't completely left my brain, the probability of drawing a straight from a deck of 52 cards in the first 5 cards is: 1/52 * 32/51 * 12/50 * 8/49 * 4/48 == ~0.0000394It shouldn't be hard to write a program that enumerated all the probabilities for drawing a straight in the first 6 ... 17 cards, then combining them. Wouldn't that be ... more accurate ... than Monte Carlo methods?
Sun, Apr. 29th, 2007 02:35 am (UTC)
bramcohen

It would be exact, but doing it is rather hard, because the probabilities of overlapping subsets forming a straight are highly correlated. And even if you compute exactly the expected number of hands for a flush to come up and a straight to come up, that doesn't necessarily indicate which one is likely to come up first, because flushes and straights showing up have an inverse correlation.
Sat, Apr. 28th, 2007 11:37 pm (UTC)
gjm11
Monte Carlo says you get a flush first about 54.5% of the time, a straight first about 36% of the time, and both at once about 9.5% of the time. Here's some brain-dead Python code to do the calculation, for anyone who fancies checking my numbers. I don't know exactly how good the Python RNG is, but I'd be very surprised if it were bad enough to put the result in any doubt.
import random
cards = list(range(52)) # bottom 2 bits are suit
def play():
# return 0 for a tie, 1 for flush first, -1 for straight first
random.shuffle(cards)
suits = [0,0,0,0]
denominations = [0]*13
for card in cards:
suit = card&3
denom = card>>2
suits[suit] += 1
f = (suits[suit]>=5)
denominations[denom] = 1
a,b = denom,denom
while a>=0 and denominations[a]: a -= 1
while b<13 and denominations[b]: b += 1
s = (b-a >= 6)
if f+s: return f-s
def count(n):
r = {-1:0,0:0,1:0}
for i in range(n): r[play()] += 1
return r
One invocation of count(1000000) returned {0: 94637, 1: 544618, -1: 360745}. The standard deviation on the number of flush-first results should be about 500, so there doesn't seem much room for doubt that the actual frequency is more than 50%. Still less room for doubt that the frequency of straight-first deals is well below 50%.
Sun, Apr. 29th, 2007 12:18 am (UTC)
gorgonous: My numbers are pretty similar:

Flush: 562222 (56.22%) Straight: 346663 (34.67%) Tie: 91115 (9.11%)
Wed, May. 2nd, 2007 05:16 pm (UTC)
bramcohen: Re: My numbers are pretty similar:

The other numbers we've come up with are off from yours by way more than the standard deviation, so either gjm's code or yours (I'm guessing yours, since I've checked gjm's code with the caveat that his first pass missed some poker knowledge) is buggy.
Sun, Apr. 29th, 2007 12:36 am (UTC)
bramcohen

You missed the case that a straight can be 10 J Q K A.
Sun, Apr. 29th, 2007 11:43 am (UTC)
gjm11
No, actually I missed (more precisely: didn't know about; I'm not a poker player) the fact that a straight can be A 2 3 4 5. Anyway, with that fixed I get 51.0% / 39.0% / 99.5% from a 1000000-deal run. Notional standard deviations are still all below 0.05%. Flushes are still comfortably ahead. These numbers don't fit well with gorgonous's. (Even my earlier ones don't, but these fit much worse.) I re-ran with a couple of different random number generators and the results didn't change any more than you'd expect by chance. So either my code or gorgonous's is broken. Here's mine as it currently stands. import random
cards = list(range(52)) # bottom 2 bits are suit
straights = [31<<i for i in range(9)] + [1+(15<<9)]
rng = random.random() # or random.WichmannHill() or random.SystemRandom()
def play():
# return 0 for a tie, 1 for flush first, -1 for straight first
rng.shuffle(cards)
suits = [0,0,0,0]
denominations = 0
for card in cards:
suit = card&3
denom = 1<<(card>>2)
suits[suit] += 1
f = (suits[suit]>=5)
denominations |= denom
s=0
for pattern in straights:
if (denominations&pattern) == pattern: s=1
if f+s: return f-s
def count(n):
r = {-1:0,0:0,1:0}
for i in range(n): r[play()] += 1
return r
Sun, Apr. 29th, 2007 03:06 pm (UTC)
bramcohen

rng.shuffle() doesn't work on my system, it has to be random.shuffle() (which defaults to using random.random() for its seed). If you want to do a trial run with a different original seed, the place to get that is os.urandom(), by the way. In a ten million sample run on my machine, which takes less than 20 minutes, I get {0: 996482, 1: 5104402, -1: 3899116}, which is almost exactly 51/39/10. My guess is that these numbers are correct and gorgonous's are off. To get legalistic about the ace thing, either case is isomorphic, but A more closely resembles 1 than 14, and started its life out that way. Ace-high was added as an american root for the underdog kind of thing.
Sun, Apr. 29th, 2007 07:20 pm (UTC)
gjm11
Hm. It looks like shuffle became a method on the Random class back in 2001. Just which version of Python are you using?
I'm in no doubt at all that my code genuinely produces the numbers I described; the question is whether there's another bug in it that neither you nor I have noticed. If not, then I agree that gorgonous must have slipped up somewhere.
Er, of course I meant 9.95% rather than 99.5% before :-).
Mon, Apr. 30th, 2007 11:52 am (UTC)
bramcohen

I think you meant to say rng = random.Random() The statement rng = random.random() sets it to a float (note capitalization)
Mon, Apr. 30th, 2007 12:48 pm (UTC)
gjm11
Aargh, typo. Sorry. I'm not quite sure how that happened!
Wed, May. 2nd, 2007 05:33 pm (UTC)
gorgonous

Ah.. I missed A2345 as well. Will correct and check again when I have access to the box that code is on.
Sun, Apr. 29th, 2007 02:00 am (UTC)
bramcohen

list(range(52)) is redundant by the way. range() returns a list, and xrange() returns a generator. This will change in Python 3000, where range() will return a generator, and there will be no xrange().
Sun, Apr. 29th, 2007 11:45 am (UTC)
gjm11
Code is cheaper than brain cells; I couldn't be bothered to check whether range returned a list or a tuple. And, as you mention, in the future (when doubtless people in their thousands will still be running my program) it'll be a generator. You can't use random.sort on either a tuple or a generator.
Sun, Apr. 29th, 2007 02:54 pm (UTC)
bramcohen

It matters more in the other direction: you shouldn't use range() for your loop counter, because it can suck down a lot of memory (particularly in cases like this one). The line really should be for i in xrange(n): r[play()] += 1 But again, this will change in python 3000, where list(range(n)) will be applicable exactly where you think it should be.
Sun, Apr. 29th, 2007 03:14 pm (UTC)
gjm11
Yup, fo' sho' xrange is better there in real code. But cut me some slack; it's just a quick hack. When there aren't real performance issues -- which there aren't here since no one's going to run it with n much more than 1000000, at which point it costs maybe 0.5s and 16MB -- I give preference to aesthetics and prefer "range" over the ugly and arbitrary "xrange". :-)
Wed, May. 2nd, 2007 05:17 pm (UTC)
bramcohen

Yeah, that's why xrange() is going away - people mis-use range() just because xrange() is ugly.
Tue, May. 1st, 2007 08:07 pm (UTC)
cparnot: nice!
Nice statistical trick. Clearly, the flush/straight odds invert as you add more card, and the odds are only good for straights at low number of cards. Combining the probability for n=5 to 17 (no need to go further) end up being in favor of flush. Really nice hunch you had here. I wonder if somebody is going to bother coming up with the exact statistics on that!
Sun, Jul. 22nd, 2007 03:09 am (UTC)
nocklas
Interesting problem. I wrote a program to do some simulations in C++ to look at the percentages when one limits the maximum number of cards that are dealt with the maximum number of cards ranging from 5 to 17. Straights seem to be more probable than flushes when the limit is less than 12 and flushes are more probable when the limit is 12 or higher. I ran 100 000 000 simulated hands and got these results:
Maximum number of cards dealt: 5 Straight: 392224 0.392224% Flush: 196967 0.196967% Both: 1497 0.001497% Nothing: 99409312 99.4093%
Maximum number of cards dealt: 6 Straight: 1778824 1.77882% Flush: 993525 0.993525% Both: 20309 0.020309% Nothing: 97207342 97.2073%
Maximum number of cards dealt: 7 Straight: 4667029 4.66703% Flush: 2895686 2.89569% Both: 109551 0.109551% Nothing: 92327734 92.3277%
Maximum number of cards dealt: 8 Straight: 9208872 9.20887% Flush: 6329483 6.32948% Both: 370080 0.37008% Nothing: 84091565 84.0916%
Maximum number of cards dealt: 9 Straight: 15110967 15.111% Flush: 11495481 11.4955% Both: 938188 0.938188% Nothing: 72455364 72.4554%
Maximum number of cards dealt: 10 Straight: 21643452 21.6435% Flush: 18219402 18.2194% Both: 1922141 1.92214% Nothing: 58215005 58.215%
Maximum number of cards dealt: 11 Straight: 27835585 27.8356% Flush: 25922844 25.9228% Both: 3337189 3.33719% Nothing: 42904382 42.9044%
Maximum number of cards dealt: 12 Straight: 32843436 32.8434% Flush: 33711283 33.7113% Both: 5053111 5.05311% Nothing: 28392170 28.3922%
Maximum number of cards dealt: 13 Straight: 36237134 36.2371% Flush: 40599760 40.5998% Both: 6800626 6.80063% Nothing: 16362480 16.3625%
Maximum number of cards dealt: 14 Straight: 38084953 38.085% Flush: 45824934 45.8249% Both: 8283493 8.28349% Nothing: 7806620 7.80662%
Maximum number of cards dealt: 15 Straight: 38824111 38.8241% Flush: 49082287 49.0823% Both: 9293807 9.29381% Nothing: 2799795 2.7998%
Maximum number of cards dealt: 16 Straight: 38994214 38.9942% Flush: 50614228 50.6142% Both: 9805461 9.80546% Nothing: 586097 0.586097%
Maximum number of cards dealt: 17 Straight: 38994214 38.9942% Flush: 51047705 51.0477% Both: 9958081 9.95808% Nothing: 0 0%
|