Antoni Parellada
Antoni Parellada

Reputation: 4791

R - Loop with If statement and tracking the number of successes

I want to simulate different poker hands. Through painful trial and error, I got the ranks, suits, the deck and a function to draw any given number of cards as:

suits    <- c("spd","hrt","dimd","clbs")
ranks    <- c(1:10,"J","Q","K")
deck     <- as.matrix(expand.grid('rank' = ranks, 'suit' = suits))
draw     <- function (n) deck[sample(nrow(deck), n), ]
draw(5)                         # Drawing 5 cards from the deck...

Output:

     rank suit  
[1,] "4"  "dimd"
[2,] "6"  "dimd"
[3,] "8"  "spd" 
[4,] "K"  "hrt" 
[5,] "8"  "clbs"

Now I want to find out through simulation the probability of getting different hands. I did come up with some possible loops with a counter for the number of successes but I am stuck.

Here is an example... Let me try to figure out how many full houses I get in 1000 simulations. Since a full house is defined as "three matching cards of one rank and two matching cards of another rank", I figured that the key part of the function would be to have a boolean within an if statement that takes advantage of the R function unique()==2, meaning 2 unique ranks - with 5 cards dealt, 2 unique ranks could be a full house (another possibility is four-of-a-kind with any other rank).

iterations <- 1000
counter <- 0
for (i in iterations){
s <- draw(5)
if(length(unique(s[,1])) == 2) counter <- counter + 1
}
counter

Output: [1] 0

I have tried multiple other things, including counter[i] <- 1 for successful cases, and with the idea of running a sum(counter) at the end, but all without getting the loop to work.

Upvotes: 3

Views: 218

Answers (3)

Jubbles
Jubbles

Reputation: 4570

suits    <- c("spd","hrt","dimd","clbs")
ranks    <- c(1:10,"J","Q","K")
deck     <- as.data.frame(expand.grid('rank' = ranks, 'suit' = suits))
draw     <- function (n) deck[sample(nrow(deck), n), ]

iterations <- 1000
counter <- 0
for (i in 1:iterations) {
    hand <- draw(5)
    rank_table <- table(hand[, 1])
    if (length(names(rank_table)) == 2 & min(rank_table) > 1) counter <- counter + 1 
    # could have four of a rank, one of another;
    # need to ensure two of a rank, three of another
}
counter
[1] 1

This result is not far from what is expected http://www.math.hawaii.edu/~ramsey/Probability/PokerHands.html

Upvotes: 0

Brandon Bertelsen
Brandon Bertelsen

Reputation: 44658

In your code you have:

for(i in 1000) { 
print(i)
} # 1000

It would only print once because i would iterate once as 1000.

Here's an alternative approach using rle.

iterations <- 10000
draws <- list()
for (i in 1:iterations){
  s <- draw(5)
  draws[[i]] <- all(rle(sort(s[,1]))$lengths %in% c(2,3))
  if(draws[[i]]) {
    print(s)
  }
}
summary(unlist(draws))

Upvotes: 1

Gopala
Gopala

Reputation: 10483

Using a data frame as follows, it seems to produce the result you are looking for:

suits    <- c("spd","hrt","dimd","clbs")
ranks    <- c(1:10,"J","Q","K")
deck     <- as.data.frame(expand.grid('rank' = ranks, 'suit' = suits))
draw     <- function (n) deck[sample(nrow(deck), n), ]

counter <- 0;
for (i in 1:1000) {
  df <- draw(5);
  counter <- counter + (length(unique(df$rank)) == 2)
}
counter
[1] 156

Upvotes: 1

Related Questions