The dice rolling game Boreal comes with 7 dice: 4 six-sided dice (d6), 1 ten-sided die (d10), 1 twenty-sided die (d20), and 1 thirty-sided die (d30). All the dice start at 1 and increment by 1 to their max value (d6 = max 6, d30 = max 30).
Create a function called dice_roller()
that has
the following 4 arguments with default values in parentheses: d6 (2),
d10 (0), d20 (0), d30 (0).
The function should return a list of four vectors called
d6_rolls, d10_rolls, d20_rolls,
d30_rolls, which have the results of the specified number of
rolls for the corresponding dice. If the chosen number of rolls is 0,
the sample()
function will return integer(0)
,
which is fine for our purposes
# Creating the dice roller function with the specified arguments and default values
dice_roller <-
function(
d6 = 2, # number of d6s to roll
d10 = 0, # number of d10s to roll
d20 = 0, # number of d20s to roll
d30 = 0 # number of d30s to roll
){
# Rolling the dice with sample and saving the results
d6_rolls = sample(1:6, size = d6, replace = T)
d10_rolls = sample(1:10, size = d10, replace = T)
d20_rolls = sample(1:20, size = d20, replace = T)
d30_rolls = sample(1:30, size = d30, replace = T)
# Returning a list of the 4 different vectors
return(
list(
d6_rolls = d6_rolls,
d10_rolls = d10_rolls,
d20_rolls = d20_rolls,
d30_rolls = d30_rolls
)
)
}
Once you get the function working, run the code chunk below to verify the results
## [1] "First Check - two d6 rolls: 5, 6"
## [1] "Second Check - eleven d10s: 4, 9, 4, 7, 4, 5, 1, 1, 8, 4, 6"
## [1] "Third Check - four d6, one d10, one d20 roll, one d30: 5, 2, 5, 3, 2, 3, 30"
One question in Boreal is “Roll all the dice. Will the sum of the results be at least 45?”. We want to know if we should answer with Yes or No.
Simulate rolling all 7 dice and sum the individual rolls. Repeat the results 1,000,000 times total, saving the sum of the seven rolls each time in a vector called rolls_sum_vec. PREALLOCATE A VECTOR, DO NOT APPEND TO SAVE THE RESULTS!!!
You can “manually” add the results of the 4 vectors together,
or you can use the unlist()
function to turn the list into
a vector as seen in the previous code chunk.
set.seed(2870)
# specifying the number of simulations
m <- 1e6
# Preallocating a vector to save the results
rolls_sum_vec <- rep(-1, m)
# Running the simulation
for (i in 1:m){
# Rolling all 7 dice
roll_results <- dice_roller(d6 = 4, d10 = 1, d20 = 1, d30 = 1)
# Summing up the seven rolls and saving the result
rolls_sum_vec[i] <- sum(unlist(roll_results))
}
The codechunk below will tally up how many times the seven die had the specific total
## # A tibble: 78 × 2
## roll_total n
## <dbl> <int>
## 1 7 0
## 2 8 0
## 3 9 3
## 4 10 8
## 5 11 14
## 6 12 63
## 7 13 129
## 8 14 225
## 9 15 394
## 10 16 590
## # ℹ 68 more rows
Add two columns to the sim1_results data frame:
cumul_count = the total number of rolls at the total or less
cumul_prob = the cumulative simulated probability of rolling the total or less: \(P(total \le x)\)
Then display the rows corresponding to roll totals between 40 - 49.
What is the probability that the roll total will be 45 or greater? \(P(total \ge 45)\)
\[P(total \ge 45) = 1 - P(total < 45) = 1 - P(total < 44) = 1 - 0.467 = 0.533\]
Let’s create a new scenario that’s not currently in Boreal: “Keep rolling a d6 and a d30 as long as the d30 is strictly greater than the d6. Will you roll the pair of dice at least _____ times?”
The goal of this question is to find what ____ should be so the probability of yes (at least ___ times) is as close to 55% as possible
Perform the action once: roll the d6 and d30 until the d30 result is less than or equal to the d6 result. How many times were the pair of dice rolled? The total number of rolls includes the roll that doesn’t meet the condition, so the minimum number of rolls will be 1
Have the loop stop if it takes more than 50 rolls before the d30 is less than the d6
Display the total number of rolls and the resulting pair of dice that stopped the dice rolling
set.seed(2870)
# Setting the roll counter to 0
rolls <- 0
# Initial values to make the condition in while to be TRUE
loop_rolls <- c(-2, -1)
# Performing the loop
while (loop_rolls[1] < loop_rolls[2]){
# Rolling the d6 and d20
loop_rolls <- dice_roller(d6 = 1, d30 = 1) |> unlist()
# Updating the roll count
rolls <- rolls + 1
# Checking if the number of rolls is at least 1000
if (rolls >= 50) { break }
}
rolls
## [1] 9
loop_rolls
## d6_rolls d30_rolls
## 5 4
If done correctly, the number of rolls should be 9 with the d6 = 5 and the d30 = 4
Using the code that you have in part 3a, simulate the question 100,000 times, saving just the counts in a vector call count_vec.
set.seed(2870)
# Setting the number of simulations
m <- 1e5
# Preallocating a vector
count_vec <- rep(-1, m)
# Running the simulation
for (i in 1:m){
### The code from part 3a
# Setting the roll counter to 0
rolls <- 0
# Initial values to make the condition in while to be TRUE
loop_rolls <- c(-2, -1)
# Performing the loop
while (loop_rolls[1] < loop_rolls[2]){
# Rolling the d6 and d20
loop_rolls <- dice_roller(d6 = 1, d30 = 1) |> unlist()
# Updating the roll count
rolls <- rolls + 1
# Checking if the number of rolls is at least 1000
if (rolls >= 50) { break }
}
# Saving the results of the ith iteration of the for loop
count_vec[i] <- rolls
}
Run the code chunk below to get how often the pair of dice were rolled before the d30 was no longer greater than the d6
## # A tibble: 50 × 2
## rolls n
## <dbl> <int>
## 1 1 11640
## 2 2 10515
## 3 3 9154
## 4 4 8013
## 5 5 6970
## 6 6 6304
## 7 7 5602
## 8 8 4990
## 9 9 4296
## 10 10 3813
## # ℹ 40 more rows
Add two columns to the sim2_results data frame:
prob = the simulated probability that it takes exactly that number of rolls before the d30 is no longer greater than the d6
cumul_prob = the cumulative simulated probability of requiring the number of rolls or less: \(P(rolls \le x)\)
prob_atleast = the probability of at least that many rolls: 1 - cumul_prob + prob: \(P(rolls \ge x)\)
Then display the 5 rows where prob_atleast is the closest to 0.55.
sim2_results <-
sim2_results |>
mutate(
prob = n/sum(n),
cumul_prob = cumsum(prob),
prob_atleast = 1 - cumul_prob + prob
)
# Displaying the 5 rows where prob_atleast is closest to 0.55
sim2_results |>
slice_min(
order_by = abs(prob_atleast - 0.55), n = 5
) |>
arrange(rolls)
## rolls n prob cumul_prob prob_atleast
## 1 4 8013 0.08013 0.39322 0.68691
## 2 5 6970 0.06970 0.46292 0.60678
## 3 6 6304 0.06304 0.52596 0.53708
## 4 7 5602 0.05602 0.58198 0.47404
## 5 8 4990 0.04990 0.63188 0.41802
What should the ____ in the original question be if we want the probability of Yes to be as close to 0.55 as possible? the closes probability is 0.526 which has at least 6 rolls