# Thread: Finding a 'straight' in poker.

1. Originally Posted by anon

In addition your O(n!) or whatever complexity and gazillion nested loops are reduced nicely to O(n).
Yes I guess those nested loops are actually another 'hidden' loop with an index of 5, which
is one pass for each card. But it was easy to write it as I did probaly easier than putting
another loop in. But I will have a go at that too,it probably won't look as 'pretty' though.

2. That does not seem to work at all.
All you are doing is seting the first 7 cards to ace
then counting the number you set and seeing if
still 7, which it is unsurprisingly.
iIndex is the rank of the card. For instance if iIndex == 11, a queen, then the following would indicate that you have one queen in your hand;
Code:
`Rank[iIndex]++;`
Incrementing it again, as follows would indicate that you have two queens in your hand
Code:
`Rank[iIndex]++;`
So, what is actually stored in the array at the index is the number of cards in your hand for a particular face card. It's not the rank as in ace thru king. The index number is actually the rank.

This code is from a complete poker sample

3. Now a question to you: how would you make your code work if the number of cards was a run-time variable (seeing that 7 is non-standard anyway) so the user could choose how many cards to play with?

Hint: it may be possible with recursion.

Edit:
BobS0327 - yes, that's a much more clever way to represent the hand for evaluation!

4. My idea was to first check for pairs, and then, if there were none, check for "connectors," (a card of the next highest or lowest rank) Assuming that every card has a chance to be a pivot, and every pivot has a connector, then the hand should be a straight.

Here's an implementation where I assume the deck is just a bunch of integers from 0 to 51:
Code:
```int compare_cards ( const void * pa, const void * pb )
{
const int * a = pa;
const int * b = pb;

return *a < *b ? -1 : *a > *b ? +1 : 0;
}
int has_pairs ( int hand[], size_t handsiz )
{
size_t card;
int pairs = 0;
int * hand_aux = malloc ( sizeof hand[0] * handsiz );

for ( card = 0; card < handsiz; card++ ) {
hand_aux[card] = hand[card];
}
qsort( hand_aux, handsiz, sizeof hand[0], compare_cards );
for ( card = 1; card < handsiz; card++ ) {
pairs += hand[card] / 13 == hand[card-1] / 13;
}
free( hand_aux );
hand_aux = NULL;
return pairs;
}
int straights ( int hand[], size_t handsiz )
{
int conseq;
size_t card, pivot;

if ( has_pairs( hand, handsiz ) ) return 0;

for ( pivot = 0; pivot < handsiz; pivot++ ) {
conseq = 0;
for ( card = 0; card < handsiz; card++ ) {
conseq += hand[pivot] / 13 + 1 == hand[card] || hand[pivot] / 13 - 1 == hand[card];
}
if ( conseq == 0 ) break;
}
return pivot == handsiz;
}```

5. Originally Posted by BobS0327
iIndex is the rank of the card. For instance if iIndex == 11, a queen, then the following would indicate that you have one queen in your hand;
Code:
`Rank[iIndex]++;`
Incrementing it again, as follows would indicate that you have two queens in your hand
Code:
`Rank[iIndex]++;`
So, what is actually stored in the array at the index is the number of cards in your hand for a particular face card. It's not the rank as in ace thru king. The index number is actually the rank.

This code is from a complete poker sample

Yes that is for finding cards of the same value eg 777, which pretty simple,
finding 34567 in 8743Q56 is a little trickier.

6. Yes that is for finding cards of the same value eg 777, which pretty simple,
finding 34567 in 8743Q56 is a little trickier.
Naaw. No big deal. Modified code below:

Code:
```#include <stdio.h>

#define NUMBER_OF_FACES 13
#define CARDS_IN_HAND 7
#define CARDS_NEEDED_FOR_STRAIGHT 5
int Rank[NUMBER_OF_FACES];

void CheckForStraight(void)
{
int iNumberConsecutive = 0;
int iRank  = 0;
while (Rank[iRank] == 0) iRank++;
for (; iRank < NUMBER_OF_FACES && Rank[iRank]; iRank++)
iNumberConsecutive++;
if (iNumberConsecutive >= CARDS_NEEDED_FOR_STRAIGHT)
printf("Straight up!\n");
else printf("NO straight!\n");
}

int main(void)
{
// Where iIndex is rank (face) value,
// Zero is an ace, 1 is a deuce, 2 is trey... 12 is a king
Rank[8]++;  // nine face card
Rank[7]++;  // eight face card
Rank[4]++;  // five  face card
Rank[3]++;  // four face card
Rank[11]++; // queen face card
Rank[5]++;  // six face card
Rank[6]++;  // seven face card

CheckForStraight();

return 0;
}```

7. This seems to work.

Code:
```/* straight.c */

#define MAXN        13
#define CARDSINHAND  7
#define IN_A_ROW     5

int is_straight( int* cards, int ncards ) {

int seen[ MAXN ];
int in_a_row;
int i;

for (i = 0; i < MAXN; i++) seen[ i ] = 0;    /* zero "seen" array */

for (i = 0; i < ncards; i++)                 /* set values seen to non-zero */
seen[ cards[ i ] - 1 ]++;

in_a_row = 0;                                /* see if there are IN_A_ROW in a row */
for (i = 0; i < MAXN; i++) {
if (seen[ i ]) {
if (++in_a_row >= IN_A_ROW)
return 1;
}
else
in_a_row = 0;
}
return 0;
}

int main() {
int c[] = { 4, 6, 3, 5, 7, 9, 11 };
int d[] = { 4, 6, 2, 5, 7, 9, 11 };
printf( "c: " );
printf( is_straight( c, CARDSINHAND ) ? "yes" : "no" );
printf( "\nd: " );
printf( is_straight( d, CARDSINHAND ) ? "yes" : "no" );
printf( "\n" );
}```

8. Originally Posted by oogabooga
This seems to work.

Code:
```/* straight.c */

#define MAXN        13
#define CARDSINHAND  7
#define IN_A_ROW     5

int is_straight( int* cards, int ncards ) {

int seen[ MAXN ];
int in_a_row;
int i;

for (i = 0; i < MAXN; i++) seen[ i ] = 0;    /* zero "seen" array */

for (i = 0; i < ncards; i++)                 /* set values seen to non-zero */
seen[ cards[ i ] - 1 ]++;

in_a_row = 0;                                /* see if there are IN_A_ROW in a row */
for (i = 0; i < MAXN; i++) {
if (seen[ i ]) {
if (++in_a_row >= IN_A_ROW)
return 1;
}
else
in_a_row = 0;
}
return 0;
}

int main() {
int c[] = { 4, 6, 3, 5, 7, 9, 11 };
int d[] = { 4, 6, 2, 5, 7, 9, 11 };
printf( "c: " );
printf( is_straight( c, CARDSINHAND ) ? "yes" : "no" );
printf( "\nd: " );
printf( is_straight( d, CARDSINHAND ) ? "yes" : "no" );
printf( "\n" );
}```
Yes it does work!!
That is a very clever way of doing it.
It avoids any sorting and it must be the fastest way of doing it too.
It took me a while to figure out what you were doing but it suddenly dawned on me.
You just set flag if a card is present and then look for 5 flags in a row.

I don't think it picks up 10,11,12,13,1 though (10,J,Q,K,A)
However if you change
Code:
`   if (++in_a_row >= IN_A_ROW)`
to
Code:
`   if ( (++in_a_row >= IN_A_ROW) || ( (i==MAXN-1) && seen[0]==1)  )`
I think it does. (assuming I have not introduced a bug!)
I never thought of doing it like that, well done.

9. Of course you might like to get rid of all those nasty local variables!!
Code:
```/* straight.c */
#include <stdio.h>
#define MAXN        13
#define CARDSINHAND  7
#define IN_A_ROW     5
int c[] = { 4, 6, 3, 5, 7, 9, 11 };
int d[] = { 4, 1, 12, 13, 10, 2, 11 };
int *ptr;
int buf[13];
int in_a_row;
int x,i;
count(){
in_a_row = 0;
for (x=0; x<MAXN ; x++)	buf[x]=0;                        //clear buffer
for (x=0; x<CARDSINHAND; x++) buf[ptr[x]-1]=1; //set flag for cards found
for (i = 0; i < MAXN; i++) {                                     //see if there are IN_A_ROW in a row
if (buf[ i ]) {
if (     (++in_a_row >= IN_A_ROW)||  ( (i==MAXN-1) && buf[0]==1)   )
return 1;
}
else  in_a_row = 0;
}
return 0;
}
int main() {
ptr=c;
printf( "c: " );
printf( count() ? "yes" : "no" );
ptr=d;
printf( "\nd: " );
printf( count() ? "yes" : "no" );
printf( "\n" );
}```
Now to me that looks easier to follow and less complex and is probably what I would
have done if I had thought of the method myself. Although I might have passed
the pointer to the function. Might not have returned a value though

10. Different version of the game have different numbers of cards in the hand, (don't they?) i dunno, i don't remember, i only ever play the ubiquitous(?) texas hold em now.
Hey Esbo, i know all those odds calculators are out there, but if you just used published programs there'd be no will to write anything of your own would there!?
Maybe you or anyone that fancies it could try writing one that just shows how often in holdem you are likely to get a pair dealt in the community cards, say with five players at table (i.e. 10 cards dealt already)
This is one thing that really cracks me up and i always think i am being cheated when it seems to happen a lot haha! because you know you are sitting on nice pair of kings, then a flamin 2comes out on the river to make a pair in the community cards an you just know some turkey that stayed in hopin, has another crummy two an is now holdin three, man that kills me haha!
i doubt i am being cheated of course, its just hard luck, but i started writing a routine to prove it but got distracted with something else in the end, i don't think i fully finished it.
Another version is how likely that one of the other players is holding a third or fourth card,

11. I don't think it picks up 10,11,12,13,1 though (10,J,Q,K,A)
Well spotted!
It now counts ace as both low and high. (Note MAXN is now 14.
I also (believe I) fixed another bug in the for(i=MAXN-1... line
by making the test a little more complex.

I definitely agree that
for (i = 0; i < MAXN; i++)
is simpler, and it's how I first did it.
But in optimizing, I realized that it does not actually
need to scan to the end (all MAXN positions of cards)
if there is no chance of a straight (not enough cards
left compared to in_a_row). Unfortunately, this required
basically doing it backwards.
It's one of those balance issues between easier to understand
and slightly faster. Usually I go for easier to understand,
but I assumed you were looking for the fastest way.

I'll stay out of the political "globals vs locals" debate,
except to mention that 8 out of 10 programmers agree that the
use of locals discourages terrorism.

Code:
```/* straight.c */

#define MAXN        14  /* 13 cards plus an extra space for ace high */
#define CARDSINHAND  7
#define IN_A_ROW     5

int is_straight( int* cards, int ncards ) {

int seen[ MAXN ];
int in_a_row;
int i;

for (i = 0; i < MAXN; i++) seen[ i ] = 0;

for (i = 0; i < ncards; i++) {
seen[ cards[ i ] - 1 ]++;
if (cards[ i ] == 1) seen[ MAXN - 1 ]++; /* Set ace as high also */
}

in_a_row = IN_A_ROW;
for (i = MAXN - 1; i + 1 >= in_a_row; i--) {
if (seen[ i ]) {
if (--in_a_row == 0)
return 1;
}
else
in_a_row = IN_A_ROW;
}
return 0;
}

int main() {
int c[] = {  1,  3,  2,  9,  5,  4, 11 };  /* 1,  2,  3,  4,  5,  9, 11 */
int d[] = { 11,  1,  3, 13,  7,  9,  5 };  /* 1,  3,  5,  7,  9, 11, 13 */
int e[] = {  5, 12, 10,  7,  1, 11, 13 };  /* 1,  5,  7, 10, 11, 12, 13 */
int f[] = { 12,  5, 11,  6, 10,  8,  7 };  /* 5,  6,  7,  8, 10, 11, 12 */
printf( "c: " );   printf( is_straight( c, CARDSINHAND ) ? "yes" : "no" );
printf( "\nd: " ); printf( is_straight( d, CARDSINHAND ) ? "yes" : "no" );
printf( "\ne: " ); printf( is_straight( e, CARDSINHAND ) ? "yes" : "no" );
printf( "\nf: " ); printf( is_straight( f, CARDSINHAND ) ? "yes" : "no" );
printf( "\n" );
}```

12. Originally Posted by rogster001
Different version of the game have different numbers of cards in the hand, (don't they?) i dunno, i don't remember, i only ever play the ubiquitous(?) texas hold em now.
Hey Esbo, i know all those odds calculators are out there, but if you just used published programs there'd be no will to write anything of your own would there!?
Maybe you or anyone that fancies it could try writing one that just shows how often in holdem you are likely to get a pair dealt in the community cards, say with five players at table (i.e. 10 cards dealt already)
This is one thing that really cracks me up and i always think i am being cheated when it seems to happen a lot haha! because you know you are sitting on nice pair of kings, then a flamin 2comes out on the river to make a pair in the community cards an you just know some turkey that stayed in hopin, has another crummy two an is now holdin three, man that kills me haha!
i doubt i am being cheated of course, its just hard luck, but i started writing a routine to prove it but got distracted with something else in the end, i don't think i fully finished it.
Another version is how likely that one of the other players is holding a third or fourth card,

Yes there are several variates of poker, there is also stud poker where you get
dealt 7 cards alll to your self but its still 7 cards in total.
The there is Omaha where you get dealt 4 cards and the there are 5 'community'
cards, however you can only use 2 of your 4 card and indeed you must use 2 unlilke
Texas where you can just use 1 or even none (just use the 5 community cards).

So the Omaha variation would be even trickier. I guess you could just run the
search for each of the 6 possible pairs or run it once with all nine cards and then
check 2 'pocket' cards are used.

You should get a pair every 17 hands. The first card is irrelvant there are then 3 cards
which it can pair with, so that is 3 in 51 or 1 in 17, a nice round number. Trouble is they are
a bit like buses, you wait for ages and then a load appear in a run. Typically when you have KK someone will have AA!!

I always suspect there is likely to be cheating but it is probably unfounded but there was a case at Absolute Poker where a guy who worked there could see other people cards.

I once checked I was getting my fair share of pocket cards but I never looked at straights
or flushes. It would take a fair bit of work to do it and it wuld not prove all was legitimate anyway as its a complex game.

13. Exactly. You get a pair every 17 hands, which is another way of saying
don't wait for the bus! But how often do they show up at the table, in
anybody's hand?

As for the odds of a pair in the community cards, that is simply the
odds of a pair in any 3 random cards, so to get a sense for it you
could shuffle a pack of cards and take off three-card packets
one by one. By the calculation below, you should get a pair almost
1 out of every 5 times (specifically, 17%).
Code:
```Number of possible 3-card combinations:
n = 52 * 51 * 50 = 132600
Number of possible 3-card combinations _without_ a pair:
m = 52 * 48 * 44 = 109824
Probability of 3-card combination not having a pair:
m / n     = 0.8282
So probability of 3-card combination having a pair:
1 - m / n = 0.1718```

14. Originally Posted by oogabooga
Exactly. You get a pair every 17 hands, which is another way of saying
don't wait for the bus! But how often do they show up at the table, in
anybody's hand?

As for the odds of a pair in the community cards, that is simply the
odds of a pair in any 3 random cards, so to get a sense for it you
could shuffle a pack of cards and take off three-card packets
one by one. By the calculation below, you should get a pair almost
1 out of every 5 times (specifically, 17%).
Code:
```Number of possible 3-card combinations:
n = 52 * 51 * 50 = 132600
Number of possible 3-card combinations _without_ a pair:
m = 52 * 48 * 44 = 109824
Probability of 3-card combination not having a pair:
m / n     = 0.8282
So probability of 3-card combination having a pair:
1 - m / n = 0.1717647```
I usually do rough calculations for such things.
I would have have said there are 3 ways of 3 of a kind 110, 101, and 011
All of which are 17-1.
However this gives 0.1764706 which is close to your figure but not spot on.
Then I was thinking 3 of a kind would explain the difference, however it came
to twice the difference (or half I forget) so I had to think it through properly.

I do not think 110 is 1 in 17 it is 1/17X 48/50 (the last card cannot be the same) which is 0.0564706 which times 3 is 0.1694118 which gives a difference of 0.0023529.
3 of a kind is 1/17X1/25 which is also 0.0023529!!!
Glad that worked!! (I amended your rounded figure above) (1 - m / n = 0.1717647).

I am glad you put that in because it made me realise my way of doing things was slightly wrong.

I have been trying to figure out the chance of 'flopping a straight' but it seems rather
complicated!!

However I will have a go say hold 67, the cards you need are 8 9 10 or 5 8 9 or 4 5 8 or 3 4 5 that is (4 ways), but....they can be in any order eg 3 4 5 or 3 5 4 or 4 3 5 or 4 5 3 or or 5 3 4 or 5 4 3. (6 ways).

So.. one single way if 4/50X4/49X 4/48=0.0005442 so times by 6 and 4 = 0.0130612
Which is 1 in 76.56.

Now to look up the correct answer on the net (it seems in the right 'ball park')

http://www.flopturnriver.com/Common-Flop-Odds.html

"flopping a straight (including the slight chance of a straight flush in some cases) 1.306%"!!
Which is the same as 0.0130612.

Well I am pleasantly surprised that was correct!!!

Well thats given me a bit more confidence in doing those sort of calculations now.

When I play online I just do very rough calculations for example if I have 4 cards to
a flush with two to come I say it is 5-1 (0.2).There are 9 'outs' left and about 47 in the pack
so thats 9/47= 0.1912. However usually you have 2 cards to come so I say I have 2 in 5
chance. Mind you there are other matters to consider such as what your opponent has, or
whether the cards seem to be running against you. Sometimes you just know your will lose!
There is always a guy at the table who just seem to win all the time!!

15. In a previous post I gave the probability for a pair in 3 cards,
but that's just the flop. As shown below, for all 5 community cards
the odds are basically 50/50, so that's why you see so many pairs
on the table!
Code:
```Number of possible 5-card combinations:
n = 52 * 51 * 50 * 49 * 48 = 311875200
Number of possible 5-card combinations _without_ a pair:
m = 52 * 48 * 44 * 40 * 36 = 158146560
Probability of 5-card combination not having a pair:
m / n     = 0.5051
So probability of 5-card combination having a pair:
1 - m / n = 0.4929```