user2187731
user2187731

Reputation: 43

Using R as a game simulator

I am trying to simulate a simple game where you spin a spinner, labeled 1-5, and then progress on until you pass the finish line (spot 50). I am a bit new to R and have been working on this for a while searching for answers. When I run the code below, it doesn't add the numbers in sequence, it returns a list of my 50 random spins and their value. How do I get this to add the spins on top of each other, then stop once => 50?

SpacesOnSpinner<-(seq(1,5,by=1))
N<-50
L1<-integer(N)

for (i in 1:N){
takeaspin<-sample(SpacesOnSpinner,1,replace=TRUE)
L1[i]<-L1[i]+takeaspin
} 

Upvotes: 4

Views: 290

Answers (3)

flodel
flodel

Reputation: 89107

Here is another interesting way to simulate your game, using a recursive function.

spin <- function(outcomes = 1:5, start = 0L, end = 50L)
   if (start <= end)
      c(got <- sample(outcomes, 1), Recall(outcomes, start + got, end))

spin()
# [1] 5 4 4 5 1 5 3 2 3 4 4 1 5 4 3

Although elegant, it won't be as fast as an improved version of @Simon's solution that makes a single call to sample, as suggested by @Viktor:

spin <- function(outcomes = 1:5, end = 50L) {
   max.spins <- ceiling(end / min(outcomes))
   x <- sample(outcomes, max.spins, replace = TRUE)
   head(x, match(TRUE, cumsum(x) >= end))
}

spin()
# [1] 3 5 2 3 5 2 2 5 1 2 1 5 5 5 2 4

For your ultimate goal (find the probability of one person being in the lead for the entire game), it is debatable whether while will be more efficient or not: a while loop is certainly slower, but you may benefit from the possibility of exiting early as the lead switches from one player to the other. Both approaches are worth testing.

Upvotes: 3

Simon O&#39;Hanlon
Simon O&#39;Hanlon

Reputation: 60000

This is a good use-case for replicate. I'm not sure if you have to use a for loop, but you could do this instead (replicate is a loop too):

SpacesOnSpinner<-(seq(1,5,by=1))
N<-10
cumsum( replicate( N , sample(SpacesOnSpinner,1,replace=TRUE) ) )
#[1]  5 10 14 19 22 25 27 29 30 33

However, since you have a condition which you want to break on, perhaps the other answer with a while condition is exactly what you need in this case (people will tell you they are bad in R, but they have their uses). Using this method, you can see how many spins it took you to get past 50 by a simple subset afterwards (but you will not know in advance how many spins it will take, but at most it will be 50!):

N<-50
x <- cumsum( replicate( N , sample(5,1) ) )

# Value of accumulator at each round until <= 50
x[ x < 50 ]
#[1]  5  6  7  8 12 16 21 24 25 29 33 34 36 38 39 41 42 44 45 49

# Number of spins before total <= 50
length(x[x < 50])
[1] 20

Upvotes: 4

tcash21
tcash21

Reputation: 4995

You can use a while statement and a variable total for keeping track of the sum:

total <- 0
while(total <= 50){
   takeaspin<-sample(SpacesOnSpinner,1,replace=TRUE)
   total <- takeaspin + total
} 

print (total)

Upvotes: 2

Related Questions