Triangles, Random Seeds

(Section 6.4)

Example: Chance of a Triangle

Triangle From Three Sides?

Recall the function for deciding if three side-lengths can make a triangle:

isTriangle <- function(x, y, z) {
  (x + y > z) & (x + z > y) & (y + z > x)
}

Vectorization

Recall that it worked on many triangles at once.

# sides for six triangles:
a <- c(2, 4.7, 5.2, 6, 6, 9)
b <- c(4, 1, 2.8, 6, 6, 3.5)
c <- c(5, 3.8, 12, 13, 11, 6.2)
# first triangle has sides 2, 4 and 5, etc.
isTriangle(a, b, c)
[1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE

A Random Process

  • You will take a stick that is one foot long, and
  • break it randomly in two places.
  • You will have three pieces.

Probability Question:

What is the probability that the three pieces will form a triangle?

Modeling Breaks

x <- runif(1)  # the first break
y <- runif(1)  # the second break
c(x = x, y = y)
        x         y 
0.6469028 0.3942258 

Make the Pieces

a <- min(x, y); b <- max(x, y)
c(left = 0, a = a, b = b, right = 1)
     left         a         b     right 
0.0000000 0.3942258 0.6469028 1.0000000 
piece1 <- a - 0; piece2 <- b - a ; piece3 <- 1 - b
c(piece1 = piece1, piece2 = piece2, piece3 = piece3)
   piece1    piece2    piece3 
0.3942258 0.2526771 0.3530972 

Do They Make a Triangle?

isTriangle(piece1, piece2, piece3)
[1] TRUE

Repetition

runif() and isTriangle() do vectorization, so they can handle repetition. Let’s repeat the random process eight times.

x <- runif(8)  # the first breaks
x
[1] 0.64690284 0.39422576 0.61850181 0.47689114 0.13609719 0.06738439 0.12915262
[8] 0.39311793
y <- runif(8)  # the second breaks
y
[1] 0.002582699 0.620205954 0.764414018 0.743835758 0.826165695 0.422729083
[7] 0.409287665 0.539692614

Get the Sides

a <- pmin(x, y)  # pairwise min gets left breaks
a
[1] 0.002582699 0.394225758 0.618501814 0.476891136 0.136097186 0.067384386
[7] 0.129152617 0.393117930
b <- pmax(x, y)  # pairwise max gets right breaks
b
[1] 0.6469028 0.6202060 0.7644140 0.7438358 0.8261657 0.4227291 0.4092877
[8] 0.5396926
side1 <- a     # leftmost sides
side2 <- b - a  # middle sides
side3 <- 1 - b # rightmost sides

Determine Triangles

isTriangle(side1, side2, side3)
[1] FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE

A Helper-Function

This function does the job, straight from the original breaks:

makesTriangle <- function(x, y) {
  a <- pmin(x, y)
  b <- pmax(x, y)
  side1 <- a
  side2 <- b - a
  side3 <- 1 - b
  isTriangle(x = side1, y = side2, z = side3)
}

Apply Function

makesTriangle(x, y)
[1] FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE

x y side1 side2 side3 triangle
0.647 0.003 0.003 0.644 0.353 FALSE
0.394 0.620 0.394 0.226 0.380 TRUE
0.619 0.764 0.619 0.146 0.236 FALSE
0.477 0.744 0.477 0.267 0.256 TRUE
0.136 0.826 0.136 0.690 0.174 FALSE
0.067 0.423 0.067 0.355 0.577 FALSE
0.129 0.409 0.129 0.280 0.591 FALSE
0.393 0.540 0.393 0.147 0.460 TRUE

Summarise Results

triangle <- makesTriangle(x, y)
sum(triangle)
[1] 3
mean(triangle)
[1] 0.375

Encapsulate Our Work Into a Function

triangleSim <- function(reps = 10000 ) {
  cut1 <- runif(reps)
  cut2 <- runif(reps)
  triangle <- makesTriangle(cut1, cut2)
  cat("The proportion of triangles was ", mean(triangle), ".\n", sep = "")
}

Extra Feature: A Table of the Results

Add a Feature

triangleSim <- function(reps = 10000, table = FALSE ) {
  cut1 <- runif(reps)
  cut2 <- runif(reps)
  triangle <- makesTriangle(cut1, cut2)
  if ( table ) {
    cat("Here is a table of the results:\n")
    print(table(triangle))
    cat("\n")
  }
  cat("The proportion of triangles was ", mean(triangle), ".\n", sep = "")
}

Try It Out

triangleSim(table = TRUE)  # use default 10000 reps
Here is a table of the results:
triangle
FALSE  TRUE 
 7466  2534 

The proportion of triangles was 0.2534.

Extra Feature: Option to Set the Random Seed

Random Output

When you do “random stuff”, the results are liable to be different each time.

Run this command several times:

sample(colors(), size = 1)

Keeping “Random” Results the Same

What if you want to keep a record of your results?

Try setting the seed for R’s random-number generator:

set.seed(3030)
sample(colors(), size = 1)

Run this several times. It’s always the same color!

Another Starting Seed

You can start with a different seed:

set.seed(4343)
sample(colors(), size = 1)

Run this several times. It’s always the same color (but different from last time)!

Option to Set a Seed

triangleSim <- function(reps = 10000, table = FALSE, seed = NULL) {
  if ( !is.null(seed) ) {
    set.seed(seed)
  }
  cut1 <- runif(reps)
  cut2 <- runif(reps)
  triangle <- makesTriangle(cut1, cut2)
  if ( table ) {
    cat("Here is a table of the results:\n\n")
    print(table(triangle))
    cat("\n")
  }
  cat(
    "The chance of being able to form a triangle\n",
    "is approximately ", mean(triangle), ".\n", sep = ""
  )
}

Try It Out

triangleSim(seed = 3030)
The chance of being able to form a triangle
is approximately 0.2547.
triangleSim()
The chance of being able to form a triangle
is approximately 0.2524.

Encapsulation and Generalization

Encapsulation and Generalization

A method for developing a computer program according to which the programmer first designs a basic procedure, then encapsulates it in one or more functions, and then progressively generalizes these functions until the program possesses all desired features.