Flow Control: Prompts, Conditionals

(Sections 4.1 - 4.2)

Prompting the User

readline() Prompts the User

person <- readline(prompt = "What is your name?  ")
# give your name before you run the next line:
cat("Hello, ", person, "!\n", sep = "")
## What is your name?  Cowardly Lion
## Hello, Cowardly Lion!

Sometimes You Must Convert

The input is treated as a character vector, so to use it as a number you should convert it first.

number <- readline("Give me a number, and I'll add 10 to it:  ")
# give your number before you run the next line:
cat("The sum is:  ", as.numeric(number) + 10)
## Give me a number, and I'll add 10 to it:  15
## The sum is:  25

Conditionals

Making Decisions

Conditional statements allow R to make decisions that depend upon various conditions.

Let’s design a simple guessing-game for the user:

  • The computer will pick randomly a whole number between 1 and 4.
  • The user will then be asked to guess the number.
  • If the user is correct, then the computer will congratulate the user.

The Code

number <- sample(1:4, size = 1)
guess <- as.numeric(readline("Guess the number (1-4):  "))
# give your number before you run the rest:
if ( guess == number ) {
  cat("Congratulations!  You are correct.")
}

Syntax for if

if ( condition ) {
  <code to execute if condition evaluates to TRUE>
}

The condition is evaluated as a Boolean expression.

Side-Note: sample()

The sample() function randomly picks a value from the vector that is is given.

sample(1:4, size = 1)
[1] 3
  • The first argument is the vector that R will pick from;
  • the size parameter specifies how many numbers to pick.

More Examples of sample()

sample(c("win", "lose"), size = 1)
[1] "lose"
sample(1:10, size = 10) # randomly shuffles the numbers
 [1] 10  3  9  8  2  6  7  1  4  5
sample(1:10, size = 10, replace = TRUE)  # replace after each pick
 [1]  3  6  6  9  9  4 10  2  5  5

if ... else

Spell out what will happen if the condition is false:

number <- sample(1:4, size = 1)
guess <- as.numeric(readline("Guess the number (1-4):  "))
# guess before running the rest:
if ( guess == number ) {
  cat("Congratulations!  You are correct.")
} else {
  cat("Sorry, the correct number was ", number, ".\n", sep = "")
  cat("Better luck next time!")
}

Syntax for if-else

if ( condition ) {
  <code to execute if condition evaluates to TRUE>
} else {
  <other code to execute if condition evaluates to FALSE>
}

Practice

Three positive numbers \(a\), \(b\) and \(c\) form the sides of a right triangle if and only if:

\[a^2 + b^2 = c^2.\]

Write a program that prompts the user for three positive numbers \(a\), \(b\) and \(c\), and then tells the user whether or not they form a right triangle. It should work like this:

> triCheck()            > triCheck()
Enter side a: 3         Enter side a: 3
Enter side b: 4         Enter side b: 4
Enter side c: 5         Enter side c: 6
Right triangle!         Not a right triangle.

Solution to Practice Problem

triCheck <- function() {
  a <- as.numeric(readline("Enter side a: "))
  b <- as.numeric(readline("Enter side b: "))
  c <- as.numeric(readline("Enter side c: "))
  if ( a^2 + b^2 == c^2 ) {
    cat("Right triangle!")
  } else {
    cat("Not a right triangle.")
  }
}

Try it out:

triCheck()

Absolute Value

The next example will use R’s function for absolute value:

abs(-7)  # turns a negative number positive
[1] 7
abs(5)   # any number >= is left alone
[1] 5

Distance Between Two Numbers

Use abs() with subtraction to find the “distance” between two numbers. For example, 5 and 30 are 25 units apart.

abs(5 - 30)
[1] 25

Another example: checking whether or not two number a one unit apart:

abs(3 - 4)  == 1  # 3 and 4 are one unit apart
[1] TRUE
abs(3 - 5)  == 1  # 3 and 5 are NOT one unit apart
[1] FALSE

Chaining if ... else’s

number <- sample(1:4, size = 1)
guess <- as.numeric(readline("Guess the number (1-4):  "))
if ( guess == number ) {
  cat("Congratulations!  You are correct.")
} else if ( abs(guess - number) == 1 ){
  cat("You were close!\n")
  cat("The correct number was ", number, ".\n", sep = "")
} else {
  cat("You were way off.\n")
  cat("The correct number was ", number, ".\n", sep = "")
}

The ifelse() Function

Some Heights

Here are some heights:

Suppose that you have a lot of heights:

height <- c(69, 67, 70, 72, 65, 63, 75, 70)

You would like to classify each person as either “tall” or “short”, depending on whether they are respectively more or less than 71 inches in height.

Can Use ifelse()

heightClass <- ifelse(test = height > 70, 
                      yes = "tall", no = "short")
heightClass
[1] "short" "short" "short" "tall"  "short" "short" "tall"  "short"

ifelse() takes three parameters:

  • test: the condition you want to evaluate;
  • yes: the value that gets assigned when test is true;
  • no: the value assigned when test is false;

Most people don’t name them:

heightClass <- ifelse(height > 70, "tall", "short")

Application: The Triangle Inequality

If a triangle has three sides of length \(x\), \(y\) and \(z\), then the sum of any two sides must be greater than the remaining side:

\[\begin{aligned} x + y &> z, \\ x + z &> y, \\ y + z &> x. \end{aligned}\]

Can It Be a Triangle?

This function decides whether three given sides can form a triangle:

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

Try it out:

isTriangle(x = 3, y = 4, z = 5)
[1] TRUE

Many Triangles at Once

Suppose you have six sets of sides:

\[(2,4,5),(4.7,1,3.8),(5.2,8,12),\\ (6, 6, 13), (6, 6, 11), (9, 3.5, 6.2)\]

Which of them can make a triangle?

Solution

Enter the sides into three vectors:

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)

The first elements of a, b and c make the first set of sides, and so on …

Solution

Decide about them all at once:

Then we can decide about all six triples at once:

isTriangle(x = a, y = b, z = c)
[1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE

Vectorization is at work here!

Fancier Solution

Use ifelse() to classify them all at once:

triangle <- ifelse(isTriangle(a, b, c), "triangle", "not")
triangle
[1] "triangle" "triangle" "not"      "not"      "triangle" "triangle"

Practice

Earlier you wrote a program that tells whether or not three given line segments form a right triangle. Now write a function called rightTriangle() that will decide, for any number of sets of three sides, whether or not the sides form a right triangle. It should work like this:

a <- c(3,6,5,8,1)
b <- c(4,3,12,6,3)
c <- c(5,2,13,10,6)  ## first triangle is (3,4,5) ...
rightTriangle(x = a, y = b, z = c)
[1] "right triangle!" "nope"            "right triangle!" "right triangle!"
[5] "nope"           

Solution to Practice Problem

Here is one way:

rightTriangle <- function(x, y, z) {
  ifelse(x^2 + y^2 == z^2, "right triangle!", "nope")
}