rrandomcoin-flipping

Random coin flipping while loop in


i'm trying to make a simple coin-flipping program. once either 'heads' or 'tails' has reached 3, the coin-flipping while loop closes. it made sense to use a random integer from sample() to generate either a 1 or a 2 to add to the tally of either heads or tails.

The problem is that the coin_flip doesn't seem to change on subsequent iterations of the while loop. So my question: how can i make it so that:

  1. coin_flip actually changes on subsequent iterations of the while loop
  2. I don't receive both 'Heads!' and 'Tails' on each iteration of the while loop

Many thanks Rohan

This is my code

heads <- 0
tails <- 0
coin_flip <- sample(1:2, 1)
print(coin_flip)

while (heads < 3 & tails < 3) {
  coin_flip
  print(coin_flip)
  if (coin_flip <- 1) {
    print ('Heads!')
    heads = heads + 1 }
  if (coin_flip <- 2) {
    print ('Tails!')
    tails = tails + 1}
} 

Solution

  • You've got 2 problems:

    1. The value of coin_flip is only changed when you assign a new value to it, coin_flip <- .... The only time you assign a random value is before the loop. If you want to get a new random value each time through the loop, that needs to happen inside the loop.

    2. Related, we use <- to assign a value, and == to test equality. You are using <- inside your if() statement so you are assigning a value. We need to use == there instead to test for equality.

      Your code, if (coin_flip <- 1) is the same as coin_flip <- 1; if(coin_flip), and if() will consider any non-zero number as TRUE.

    Fixing those, we get this:

    heads <- 0
    tails <- 0
    while (heads < 3 & tails < 3) {
      coin_flip <- sample(1:2, 1)
      print(coin_flip)
      if (coin_flip == 1) {
        print ('Heads!')
        heads = heads + 1 }
      if (coin_flip == 2) {
        print ('Tails!')
        tails = tails + 1}
    } 
    # [1] 2
    # [1] "Tails!"
    # [1] 1
    # [1] "Heads!"
    # [1] 2
    # [1] "Tails!"
    # [1] 1
    # [1] "Heads!"
    # [1] 1
    # [1] "Heads!"
    

    If we wanted to simplify a little bit, I would say there's no reason to sample numbers when we could sample from "Heads" and "Tails" directly. I also generally prefer message() to print() for single-line notes about how code is running. This would let us remove some unnecessary bits like this:

    heads <- 0
    tails <- 0
    while (heads < 3 & tails < 3) {
      coin_flip <- sample(c("Heads", "Tails"), 1)
      message(coin_flip)
      if (coin_flip == "Heads") {
        heads = heads + 1
      }
      if (coin_flip == "Tails") {
        tails = tails + 1
      }
    } 
    # Heads
    # Tails
    # Heads
    # Heads
    

    Here's a little more concise, using a named vector for the results instead of two separate objects. This lets us skip the if() statements entirely, using the result as a name to increment the correct value.

    results = c("Heads" = 0, "Tails" = 0)
    while (all(results < 3)) {
      coin_flip <- sample(c("Heads", "Tails"), 1)
      message(coin_flip)
      results[coin_flip] <- results[coin_flip] + 1
    }