Dice Description

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).

Question 1: Dice Rolling Function

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
      )
    )
    
  }

Validating the function

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"

Question 2: First Simulation

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.

Part 2a: Simulate rolling all the dice 1,000,000 times

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

Part 2b: Will the total be over 45?

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\]

Question 3: Second Simulation

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

Part 3a: Rolling the d6 and a d30 until the condition is met

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

Part 3b: Simulate the results 100,000 times

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

Part 3c: Will the total be over 45?

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