4 FlowControl
In the above scene from the comicstrip Foxtrot, young Jason has attempted to shortcut his “writeontheblackboard” punishment via some code in the Clanguage that would print out his assigned sentence 500 times. This is an example of flow control.
Flow control encompasses the tools in a programming language that allow the computer to make decisions and to repeat tasks. In this Chapter we will learn how flow control is implemented in R.
4.1 Prompting the User
One way to control the flow of a program is to arrange for it to pause and await information from the user who runs it.
Up to this point any information that we have wanted to process has had to be entered into the code itself. For example, if we want to print out a name to the console, we have to provide that name in the code, like this:
person < "Dorothy"
cat("Hello, ", person, "!\n", sep = "")
## Hello, Dorothy!
We can get any printout we like as long as we assign the desired string to person
—but we have to do that in the code itself. But what if we don’t know the name of the person whom we want to greet? How can we be assured of printing out the correct name?
The readline()
function will be helpful, here. It reads input directly from the console and produces a character vector (of length one) that we may use as we like. Thus
person < readline(prompt = "What is your name? ")
# Type your name before running the next line!
cat("Hello, ", person, "!\n", sep = "")
## What is your name? Cowardly Lion
## Hello, Cowardly Lion!
Note that the input obtained from readline()
is always a character vector of length one—a single string—so if you plan to use it as a number then you need to convert it to a number. The as.numeric()
function will do this for you:
number < readline("Give me a number, and I'll add 10 to it: ")
# Give R 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
4.1.1 Practice Exercises

Try out the following code:
pet < readline("Enter the name of your pet: ") type < readline("What kind of animal is it? (Dog, cat, etc.): ") cat(pet, " is a ", type, ".\n", sep = "")
Important: Run the lines one at a time, not all three at once. R will stop after the first line, waiting for your answer. If you try to run line 2 along with the
pet
line, then line 2 will become your attempted input forpet
, resulting in an error.
4.1.2 Solutions to the Practice Exercises

Here’s one possible outcome in the Console:
> pet < readline("Enter the name of your pet: ") Enter the name of your pet: Bo > type < readline("What kind of animal is it? (Dog, cat, etc.): ") What kind of animal is it? (Dog, cat, etc.): dog > cat(pet, " is a ", type, ".\n", sep = "") Bo is a dog.
4.2 Making Decisions: Conditionals
Another type of flow control involves determining which parts of the program to execute, depending upon certain conditions.
4.2.1 If Statements
Let’s design a simple guessinggame 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.
number < sample(1:4, size = 1)
guess < as.numeric(readline("Guess the number (14): "))
if ( guess == number ) {
cat("Congratulations! You are correct.")
}
The sample()
function randomly picks a value from the vector that is is given. The size
parameter specifies how many numbers to pick. (This time we only want one number.)
Flow control enters the picture with the reserved word if
. Immediately after if
is a Boolean expression enclosed in parentheses. This expression is often called the condition. If the condition evaluates to TRUE
, then the body of the if
statement—the code enclosed in the brackets—will be executed. On the other hand if the condition evaluates to FALSE
, then R skips past the bracketed code.^{13}
The general form of an if
expression is as follows:
if ( condition ) {
## code to run when the condition evaluates to TRUE
}
The code above congratulates the a lucky guesser, but it has nothing at all to say to someone who did not guess correctly. The way to provide an alternative is through the addition of the else
reservedword:
number < sample(1:4, size = 1)
guess < as.numeric(readline("Guess the number (14): "))
if ( guess == number ) {
cat("Congratulations! You are correct.")
} else {
cat("Sorry, the correct number was ", number, ".\n", sep = "")
cat("Better luck next time!")
}
The general form of an ifelse
expression is as follows:
if ( condition ) {
# code to run if the condition evaluates to TRUE
} else {
# code to run if condition evaluates to FALSE
}
An ifelse
can be followed by any number of ifelse
’s, setting up a chain of alternative responses:
number < sample(1:4, size = 1)
guess < as.numeric(readline("Guess the number (14): "))
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 = "")
}
In general, a chain looks like this:
if ( condition1) {
# code to run if condition1 evaluates to TRUE
else if ( condition2 ) {
} # code to run if condition2 evaluates to TRUE
else if ( condition3 ) {
} # code to run if condition2 evaluates to TRUE
else if ......
}
# and so on until
} else if ( conditionN ) {
# code to run if conditionN evaluates to TRUE
}
4.2.2 Application: Validating Arguments
Recall the function manyCat()
:
manyCat < function(word, n) {
wordWithNewline < paste(word, "\n", sep = "")
lines < rep(wordWithNewline, times = n)
cat(lines, sep = "")
}
What would happen if a user were to call it with an unusable argument for the parameter n
, a negative number, for instance?
manyCat(word = "Hello", n = 3)
## Error in rep(wordWithNewline, times = n): invalid 'times' argument
For us, it’s clear enough what is wrong. After all, we wrote the function in the previous chapter, and we know that the rep()
function in its body requires that the times
parameter be set to some positive integer. On the other hand, to someone who is unfamiliar with the body of manyCat()
and who has no access to help on how manyCat()
is to be used it may not be so obvious what has gone wrong and why.
In the case of complex functions, we cannot expect ordinary users to search through the function’s definition to learn how to fix an error that arises from improper input. Accordingly, it can be good practice to validate userinput. Conditionals allow us to do this.
Here, a possible approach is to attempt to coerce the user’s input for n
into an integer, using the as.integer()
function:
as.integer(3.6) # will round to nearest integer
## [1] 3
as.integer("4") # will convert string to number 4
## [1] 4
as.integer("4.3") # will convert AND round
## [1] 4
as.integer("two") # cannot convert to integer
## Warning: NAs introduced by coercion
## [1] NA
In the last example, the result is NA
, and a cryptic warning was issued. In order to keep the warning from the user, we should wrap any call to as.integer()
in the suppressWarnings()
function.
Let’s try out a piece of code that checks for validity:
n < "two" # this will not convert to a number at all
converted < suppressWarnings(as.integer(n))
!is.na(converted) && converted >= 1
## [1] FALSE
Think about what happened:
 First we attempted to converted the
"two"
to an integer.  Since the result of
as.integer("two")
isNA
, the expressionis.na(converted)
evaluates toTRUE
 Hence
!is.na(converted)
evaluates toFALSE
.  Hence
!is.na(converted) && converted > 1
evaluates toFALSE
.
Let’s try it on another “wrong” value:
n < 2 # number, but it's negative
converted < suppressWarnings(as.integer(n))
!is.na(converted) && converted >= 1
## [1] FALSE
This time converted
gets an assigned value, namely 2, but since it’s not at least 1 the expression !is.na(converted) && converted >= 1
evaluates to FALSE
.
Now let’s try it on a “good” value:
n < 3
converted < suppressWarnings(as.integer(n))
!is.na(converted) && converted >= 1
## [1] TRUE
Our code appears to be working well.
Now that we’ve figured out a way to determine whether any given input is a usable number, let’s employ a conditional to implement validation in manyCat()
:
manyCat < function(word, n) {
n < suppressWarnings(as.integer(n))
isValid < !is.na(n) && n >= 1
if (!isValid) {
message < "Sorry, n must be a whole number at least 1.\n"
return(cat(message))
}
wordWithNewline < paste(word, "\n", sep = "")
lines < rep(wordWithNewline, times = n)
cat(lines, sep = "")
}
The idea is to force an early return—along with a helpful message to the Console—if the user’s argument for n
is no good.
Let’s watch it in action:
manyCat(word = "Hello", n = "two") # problem!
## Sorry, n must be a whole number at least 1.
manyCat(word = "Hello", n = 3) # OK
## Hello
## Hello
## Hello
4.2.3 Application: Invisible Returns
Let’s think again about the \(\pi\)computing function from Section 3.4.1:
madhavaPI < function(n = 1000000) {
k < 1:n
terms < (1)^(k+1)*4/(2*k1)
sum(terms)
}
We could use if
to write in a “talky” option:
madhavaPI < function(n = 1000000, verbose = FALSE) {
k < 1:n
terms < (1)^(k+1)*4/(2*k1)
approx < sum(terms)
if ( verbose) {
cat("Madhava's approximation is: ", approx, ".\n", sep = "")
cat("This is based on ", n, " terms.\n", sep = "")
}
approx
}
Try it out:
madhavaPI(n = 1000, verbose = TRUE)
## Madhava's approximation is: 3.140593.
## This is based on 1000 terms.
## [1] 3.140593
It’s a bit awkward that the approximation gets printed out at the end: after the message on the console, the user doesn’t need to see it. But if we were to remove the final approx
expression, then the function would not return an approximation that could be used for further computations.
The solution to this dilemma is R’s invisible()
function.
madhavaPI < function(n = 1000000, verbose = FALSE) {
k < 1:n
terms < (1)^(k+1)*4/(2*k1)
approx < sum(terms)
if ( verbose) {
cat("Madhava's approximation is: ", approx, ".\n", sep = "")
cat("This is based on ", n, " terms.\n", sep = "")
}
invisible(approx)
}
If you wrap an expression in invisible()
, then it won’t be printed out to the console:
madhavaPI(n = 1000, verbose = TRUE)
## Madhava's approximation is: 3.140593.
## This is based on 1000 terms.
Nevertheless it is still returned, as we can see from the following code, in which the approximation is computed without any output to the console and stored in the variable p
for use later on in a cat()
statement.
p < madhavaPI() # verbose is FALSE by default
cat("Pi plus 10 is about ", p + 10, ".", sep = "")
## Pi plus 10 is about 13.14159.
4.2.4 Ifelse
The ifelse()
function is a special form of the ifelse construct that is used to make assignments, and is especially handy in the context of vectorization.
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. ifelse()
makes quick work of it:
heightClass < ifelse(test = height > 70,
yes = "tall", no = "short")
heightClass
## [1] "short" "short" "short" "tall" "short" "short" "tall" "short"
Note that ifelse()
takes three parameters:

test
: the condition you want to evaluate; 
yes
: the value that gets assigned whentest
is true; 
no
: the value assigned whentest
is false;
Most programmers don’t name the parameters. This is fine—just remember to keep the testyesno order:
ifelse(height > 70, "tall", "short")
## [1] "short" "short" "short" "tall" "short" "short" "tall" "short"
Here’s another example of the power of ifelese()
. 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}\] This fact is known as the Triangle Inequality. It works the other way around, too: if three positive numbers are such that the sum of any two exceeds the third, then three line segments having those numbers as lengths could be arranged into a triangle.
We can write a function that, when given three lengths, determines whether or not they can make a triangle:
isTriangle < function(x, y, z) {
(x + y > z) & (x +z > y) & (y + z > x)
}
isTriangle()
simply evaluates a Boolean expression involving x
, y
and z
. It will return TRUE
when the three quantities satisfy the Triangle Inequality; otherwise, it returns FALSE
. Let’s try it out:
isTriangle(x = 3, y = 4, z = 5)
## [1] TRUE
Recall that Boolean expressions can involve vectors of any length. So suppose that we are would like to know which of the following six triples of numbers could be the sidelengths of a triangle:
\[(2,4,5),(4.7,1,3.8),(5.2,8,12),\\
(6, 6, 13), (6, 6, 11), (9, 3.5, 6.2)\]
We could enter the triples one at a time into isTriangle()
. On the other hand we could arrange the sides into three vectors of length six each:
Then we can decide about all six triples at once:
isTriangle(x = a, y = b, z = c)
## [1] TRUE TRUE FALSE FALSE TRUE TRUE
We could also use ifelse()
to create a new charactervector that expresses our results verbally:
triangle < ifelse(isTriangle(a, b, c), "triangle", "not")
triangle
## [1] "triangle" "triangle" "not" "not" "triangle" "triangle"
4.2.5 Switch
If you have to make a decision involving two or more alternatives you can use a chain of if ... else
constructions. When the alternatives involve no more than the assignment of a value to a variable, you might also consider using the switch()
function.
For example, suppose that you have days of the week expressed as numbers. Maybe it’s like this:
 1 stands for Sunday
 2 for Monday
 3 for Wednesday
 and so on.
If you would like to convert a daynumber to the right day name, then you could write a function like this:
dayWord < function(dayNumber) {
switch(dayNumber,
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday")
}
dayWord(3)
## [1] "Tuesday"
In switch()
above, the first argument after dayNumber
is what goes with 1, the second argument is what goes with 2, and so on.
When the item you want to convert is a string rather than a number, then the switch()
function works a little bit differently. Suppose, for instance, that you want to abbreviate the names of the weekdays. You might write an abbreviationfunction as follows:
abbrDay < function(day) {
switch(day,
Monday = "Mon",
Tuesday = "Tue",
Wednesday = "Wed",
Thursday = "Th",
Friday = "Fri",
Saturday = "Sat")
}
abbrDay("Wednesday")
## [1] "Wed"
In the above call to switch()
, the weekday names you want to abbreviate appear as the names of named charactervectors, each of length one. The value of each vector is what the its name will be converted to.
When you are converting strings you have the option to provide a default conversion for values that don’t fit into the pattern you have in mind. All you have to do is to provide the default value as an additional argument. (It should NOT have a name.) Thus:
abbrDay < function(day) {
switch(day,
Monday = "Mon",
Tuesday = "Tue",
Wednesday = "Wed",
Thursday = "Th",
Friday = "Fri",
Saturday = "Sat",
"not a weekday!")
}
abbrDay("Wednesday")
## [1] "Wed"
abbrDay("Neptune")
## [1] "not a weekday!"
4.2.6 Practice Exercises

Consider the following function:
computeSquare < function(x) { x^2 }
Write a “talky” version of the above function that returns the square invisibly.. It should be called
computeSquare2()
and should take two parameters:
x
: the number to be squared 
verbose
: whether or not tocat()
out a report to the Console.
Typical examples of use would be:
computeSquare2(4)
## The square of 4 is 16.
mySquare < computeSquare2(6, verbose = FALSE) mySquare
## [1] 36


Write a function called
findKarl()
that takes a character vector and returns a character vector that reports whether or not each element of the given vector was equal to the string"Karl"
. It should work like this:vec1 < c("three", "blowfish", "Karl", "Grindel") findKarl(vec1)
## [1] "Sorry, not our guy." "Sorry, not our guy." "Yep, that's Karl!" ## [4] "Sorry, not our guy."

Here’s a function that is supposed to return
"small!"
when given a number less than 100, and return"big!"
when the number if at least 100:sizeComment < function(x) { if ( x < 100 ) { "small!" } "big!" }
But it doesn’t work:
sizeComment(200) # this will be OK
## [1] "big!"
sizeComment(50) # this won't be OK
## [1] "big!"
Fix the code.
Add some validation to the
isTriangle()
function so that it stops the user if one or more of the parametersx
,y
andz
cannot be interpreted as a positive real number.
4.2.7 Solutions to Practice Exercises

Here’s the desired function:

Here’s one way to write it:
findKarl < function(x) { ifelse(x == "Karl", "Yep, that's Karl!", "Sorry, not our guy.") }

A function always returns the value of the last expression that it evaluates. As it stands, the function will always end at the line
"big!"
, so"big"
will always be returned. One way to get the desired behavior is to force the function to stop executing once it prints out"small!"
. You can do this with thereturn()
function:sizeComment < function(x) { if ( x < 100 ) { return("small!") } "big!" }
Another way is to use the
if ... else
construction:sizeComment < function(x) { if ( x < 100 ) { "small!" } else { "big!" } }

Here is one approach:
isTriangle < function(x, y, z) { x < suppressWarnings(as.numeric(x)) x < suppressWarnings(as.numeric(x)) x < suppressWarnings(as.numeric(x)) xValid < all(!is.na(x) & x > 0) yValid < all(!is.na(y) & y > 0) zValid < all(!is.na(z) & z > 0) if (!(xValid & yValid & zValid)) { return(cat("Sorry, all inputs must be positive real numbers.\n")) } (x + y > z) & (x +z > y) & (y + z > x) }
Try it out:
## Sorry, all inputs must be positive real numbers.
## [1] FALSE FALSE TRUE
4.3 Repeating Things: Looping
We have looked a bit into the aspect of flow control that pertains to making decisions. Let us now turn to the Rconstructs that make the computer repeat actions.
4.3.1 For Loops
The reserved word for
is used to make R repeat an action a specified number of times.
We begin with an very simple example:
for ( i in 1:4 ) {
cat("Hello, Dorothy!\n")
}
## Hello, Dorothy!
## Hello, Dorothy!
## Hello, Dorothy!
## Hello, Dorothy!
Here’s how the loop works. Recall that the vector 1:4
is simply the sequence of integers from 1 to 4:
1:4
## [1] 1 2 3 4
When R sees the code (i in 1:4)
it knows that it will have to go four times through the body of the loop.
cat("Hello, Dorothy!\n")
(The body of a loop is what’s contained in the brackets after for(i in 1:4)
). At the start of the loop, the index variable i
is set to 1. After the body is executed the first time, R sets i
to 2, then executes the body again. Then R sets i
to 3 and executes the body yet again. Then R sets i
to 4, and executes the body for the final time. The result is four lines printed out to the console.
The more you need to repeat a particular pattern, the more it makes sense to write your code with a loop.
The general form of a loop is:
for ( var in seq ) {
# code involving var
}
var
is the index variable, and it can be any permitted name for a variable, and seq
can be any vector. As R traverses the loop, the value of the index variable var
becomes each element of the vector seq
in turn. With every change in the value of var
, the code in the brackets is executed.
To iterate is to do a thing again and again. The vector seq
is sometimes called an iterable, since it is “iterated over.” It contains the values that the index variable will assume, one by one, as the loop is repeated.
It’s important to realize that the index variable can have any valid name, and the sequence can be any type of vector at all—not just a sequence of consecutive whole numbers beginning with 1. This level of generality permits a forloop to automate a wide variety of tasks, and for its code to be written in a way that evokes the operations being performed.
For example, here is a loop to print out some greetings;
people < c("Dorothy", "Tin Man", "Scarecrow", "Lion")
for ( person in people ) {
cat("Hello, ", person, "!\n", sep = "")
}
## Hello, Dorothy!
## Hello, Tin Man!
## Hello, Scarecrow!
## Hello, Lion!
Or perhaps you want to abbreviate a vectorful of weekdaynames:
weekdays < c("Saturday", "Monday", "Friday", "Saturday")
for ( day in weekdays ) {
print(abbrDay(day))
}
## [1] "Sat"
## [1] "Mon"
## [1] "Fri"
## [1] "Sat"
Quite often you will want to store the results of your trips through the loop. Let’s do this for our abbreviated weekdays:
We used the character()
function to create the character vector abbrDays
. We specified that the number of elements in abbrDays
shall be the same as the number of elements in weekdays
. Right now abbrDays
isn’t very interesting, as all of its elements are empty strings:
abbrDays
## [1] "" "" "" ""
We will now write a forloop to fill it up with abbreviations:
for ( i in 1:length(weekdays) ) {
abbrDays[i] < abbrDay(weekdays[i])
}
Now each of the four elements of abbrDays
contains the abbreviation for the corresponding element of weekdays
:
abbrDays
## [1] "Sat" "Mon" "Fri" "Sat"
You will often have reason to set up an empty vector of a definite length and use a loop to store information in it. The general format looks like this:
4.3.2 ForLoop Caution
You might need to exercise some caution in your choice name for the index variable. If you are already using it as the name for a variable in the same environment, then you will overwrite that variable, as demonstrated by the following code:
day < "Thursday"
cat("Today is ", day, ".\n", sep = "")
## Today is Thursday.
weekdays < c("Saturday", "Monday", "Friday", "Saturday")
abbrDays < character(length(weekdays))
for ( day in weekdays ) {
print(day)
}
## [1] "Saturday"
## [1] "Monday"
## [1] "Friday"
## [1] "Saturday"
cat("Today is ", day, ".\n", sep = "")
## Today is Saturday.
Of course, that won’t happen if the forloop is inside of a function and your variable is outside of it.
day < "Thursday"
cat("Today is ", day, ".\n", sep = "")
## Today is Thursday.
weekdays < c("Saturday", "Monday", "Friday", "Saturday")
listDays < function(days) {
for ( day in days ) {
print(day)
}
}
listDays(weekdays)
## [1] "Saturday"
## [1] "Monday"
## [1] "Friday"
## [1] "Saturday"
cat("Today is still ", day, ".\n", sep = "")
## Today is still Thursday.
4.3.3 Breaking Out of a Loop
Sometimes you finish the task at hand before you are done with the loop. If this is a possibility for you then you may arrange to break out of the loop with the break
reservedword.
Suppose for example that you want a function that searches through a vector for a given element, updating the user along the way as to the progress of the search. You can try something like this:
# function to find index of element in vector.
# returns 1 if elem is not in vector
verboseSearch < function(elem, vec) {
# The following logical keeps track of whether
# we have found the element.
# We have not yet begun the search so start it
# at FALSE.
found < FALSE
# validate input:
if ( length(vec) == 0 ) {
cat("The vector empty. No way does it contain ",
elem, ".", sep = "")
return(1)
}
# check the elements of vector:
for ( i in 1: length(vec) ) {
if ( vec[i] == elem ) {
# record that we found the element:
found < TRUE
break
} else {
# report no match at this index:
cat("Checked index ", i,
" in the vector. No match there ...\n", sep = "")
}
}
if ( found ) {
# report success:
cat("Found ", elem, " at index ", i, ".\n", sep = "")
return(i)
} else {
# report failure:
cat(elem, " is not in the vector.\n", sep = "")
return(1)
}
}
Let’s see our function in action:
people < c("Dorothy", "Tin Man", "Scarecrow", "Lion")
scarecrowPlace < verboseSearch("Scarecrow", people)
## Checked index 1 in the vector. No match there ...
## Checked index 2 in the vector. No match there ...
## Found Scarecrow at index 3.
In the code for verboseSearch()
you will notice that there is an initial check on the length of the vector. This is actually important. If a user were to enter an empty vector, then its length would be 0. Then in the loop the sequence would be 1:0
, which is the vector with elements 1 and 0. But look at what happens when you ask for any element of a zerolength vector:
emptyVec < character(0)
emptyVec[1] # You get NA
## [1] NA
Then check out what happens if you compare an NA
to a string:
NA == "Scarecrow"
## [1] NA
Now look at what happens in an if
statement where the condition is NA
:
if ( NA ) {
cat("We are in the bracket!\n")
}
## Error in if (NA) { : missing value where TRUE/FALSE needed
Checking that the input vector has positive length is an another example of validating input. Remember: when you write functions for other people to use it can be helpful to have the function validate its input instead of allowing R to throw obscure error messages at the user.
4.3.4 Solving the EmptyVector Problem in for
Loops with seq_along()
In the previous section we considered a possible problem with for
loops of the following form:
for ( i in 1:length(vec) ) {
## do something ...
}
In the above loop vec
could be thought of as a “loopdefining” vector: its length determines the sequence of values 1, 2, 3 … for the index i
. This sequence of values is supposed to end at the length of vec
.
The problem is that if vec
happens to be an empty vector then we probably don’t want to enter the loop at all. However, the length of an empty vector is 0, and so the vector 1:length(vec)
actually works out to be a vector with two elements:
c(1,0)
Hence R will go through the loop twice: once when i
is 1, and again when i
is 0. Depending on what the loop does, very unexpected results could be produced.
In the previous section we dealt with the problem by writing an if
statement that provides the proper response when vec
is empty. In many circumstances however, all we need to do is to make sure that the loop is skipped when the vector is empty.
A handy way to ensure skipping is to use the function seq_along()
. Given any nonempty vector, seq_along()
produces a sequencevector that begins with 1 and ends with the length of the vector, thus:
## [1] 1 2 3
On the other hand, if the vector is empty, then seq_long()
returns an empty numeric vector:
## integer(0)
Now consider the loop inside the following function:
loopy < function(vec) {
for ( i in seq_along(vec) ) {
cat("This time i is ", i, ".\n", sep = "")
}
}
Given a nonempty vector, it goes through the loop a number of times equal to the length of the vector:
loopy(c("a", "d", "f"))
## This time i is 1.
## This time i is 2.
## This time i is 3.
On the other hand, when given an empty vector the function does not enter the loop at all:
loopy(character()) # no output to console!
When you are writing a program that is complex enough that you don’t know whether the loopdefining vector might be empty, it is good practice to use seq_along()
as a safeguard.
4.3.5 Skipping Ahead in a Loop
Depending on what happens within a loop, you might sometimes wish to skip the remaining code within the loop and proceed to the next iteration. R provides the reservedword next
for this purpose. Here is a simple example:
vec < c("a","e", "e", "i", "o", "u", "e", "z")
# shout ahoy when you see the specified element
verboseAhoy < function(elem, vec) {
if (length(vec) > 0) {
for ( i in 1: length(vec) ) {
if ( vec[i] != elem) next
cat("Ahoy! ", elem, " at index ", i, "!\n", sep = "")
}
}
}
verboseAhoy("e", vec)
## Ahoy! e at index 2!
## Ahoy! e at index 3!
## Ahoy! e at index 7!
When the vec[i] !== elem
condition is true, R immediately skips the rest of the loop, increments the value of the index variable i
, and runs through the loop again.
You can always accomplish the skipping without using next
explicitly, but it’s nice to have on hand.
4.3.6 Repeat
Forloops are pretty wonderful, but they are best used in circumstances when you know how many times you will need to loop. When you need to repeat a block of code until a certain condition occurs, then the repeat
reservedword might be a good choice.
For example, suppose you want to play the numberguessing game with the user, but let her keep guessing until either she gives up or gets the correct answer. Here’s an implementation using repeat
:
n < 20
number < sample(1:n, size = 1)
cat("I'm thinking of a whole number from 1 to ", n, ".\n", sep = "")
repeat {
guess < readline("What's your guess? (Enter q to quit.) ")
if ( guess == "q" ) {
cat("Bye!\n")
break
} else if ( as.numeric(guess) == number ) {
cat("You are correct! Thanks for playing!")
break
}
# If we get here, the guess was not correct:
# loop will repeat!
}
The game works well enough, but if you give it a try, you are sure to find it a bit fatiguing. It wold be nice to give the user a hint after an incorrect guess. Let’s revise the game to tell the reader whether her guess was high or low. While we are at it, let’s cast the game into the form of a function.
numberGuess < function(n) {
number < sample(1:n, size = 1)
cat("I'm thinking of a whole number from 1 to ", n, ".\n", sep = "")
repeat {
guess < readline("What's your guess? (Enter q to quit.) ")
if (guess == "q") {
cat("Bye!\n")
break
} else if (as.numeric(guess) == number) {
cat("You are correct! Thanks for playing!")
break
}
# If we get to this point the guess was not correct.
# Issue hint:
hint < ifelse(as.numeric(guess) > number, "high", "low")
cat("Your guess was ", hint, ". Keep at it!\n", sep = "")
# Repeat loop
}
}
A typical game:
> numberGuess(100)
I'm thinking of a whole number from 1 to 100.
What's your guess? (Enter q to quit.) 50
Your guess was high. Keep at it!
What's your guess? (Enter q to quit.) 25
Your guess was high. Keep at it!
What's your guess? (Enter q to quit.) 12
Your guess was low. Keep at it!
What's your guess? (Enter q to quit.) 18
Your guess was low. Keep at it!
What's your guess? (Enter q to quit.) 22
Your guess was high. Keep at it!
What's your guess? (Enter q to quit.) 20
You are correct! Thanks for playing!
4.3.7 While
The reserved word while
constructs a loop that runs as long as a specified condition is true. Unlike repeat
, which launches directly into the loop, the condition for while
is evaluated prior to the body of the loop. If the condition is false at the beginning, the code in the body of the loop is never executed.
verboseSearch()
could be rewritten with while
:
verboseSearch < function(elem, vec) {
found < FALSE
if ( length(vec) == 0 ) {
cat("The vector is empty. No way does it contain ",
elem, ".\n", sep = "")
return(1)
}
# index of vec (start looking at 1):
i < 1
while ( !found & i <= length(vec) ) {
if ( vec[i] == elem ) {
found < TRUE
break
}
cat("No match at position ", i, " ...\n")
i < i + 1
}
if ( found ) {
# report success:
cat("Found ", elem, " at index ", i, ".\n", sep = "")
return(i)
} else {
# report failure:
cat(elem, " is not in the vector.\n", sep = "")
return(1)
}
}
4.3.8 Practice Problems

You want to compute the square roots of the whole numbers from 1 to 10. You could do this quite easily as follows:
sqrt(1:10)
## [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427 3.000000 ## [10] 3.162278
However, you want to practice using
for
loops. Write a small program that uses a loop to compute the square roots of the whole numbers from 1 to 10. Think about the practice problem
findKarl()
from the previous section. Write a new version that uses a loop.
You want to append
"the Dog"
to the end of each element of a character vector of dognames. Sadly, you have not yet realized that thepaste()
function is very much up to the task:## [1] "Bo the Dog" "Gracie the Dog" "Rover the Dog" "Anya the Dog"
You decide to use a
for
loop. Write the code. 
Write a function called
triangleOfStars()
that produces patterns liks this:**** *** ** *
It should take a single parameter
n
, the number of asterisks in the first “line” of the triangle. Use afor
loop in the body of the function. 
Write a function called
trianglePattern()
that produces patterns like the ones from the previous problem, but using any character that the user specifies. The function should take two parameters:
char
, a string giving the character to use. The default value should be"*"
. 
n
, the number of asterisks in the first “line” of the output.
Typical examples of use should be as follows:
trianglePattern(char = "x", 5)
## xxxxx ## xxxx ## xxx ## xx ## x
trianglePattern(n = 6)
## ****** ## ***** ## **** ## *** ## ** ## *

Rewrite
triangleOfStars()
so that it uses awhile
loop in its body.
Rewrite
triangleOfStars()
so that it still uses awhile
loop in its body, but produces output like this:* ** *** ****

Write a function called
cheerleader()
that badgers you for each of the letters in a word until you give it all of the letters, one by one. It should work like this:schoolMascot < c("T", "I", "G", "E", "R", "S") cheerleader(cheer = schoolMascot)
> cheerleader(cheer = schoolMascot) Gimme a T! T Gimme a I! i Gimme a I! I Gimme a G! gee Gimme a G! I said gee!! Gimme a G! G Gimme a E! E Gimme a R! Are you going to do this all day? Gimme a R! R Gimme a S! Stop it, please! Gimme a S! S >

Write a function called
ageReporter()
that reports the ages of given individuals. It should take two parameters:
people
: a character vector of names of the people of interest. 
ages
: a vector containing the ages of the people of interest.
The function should perform some validation: it should stop the user with a helpful message if the number of people supplied and the number of ages supplied are not the same, or if one of the supplied vectors has length zero.
Typical examples of use would be as follows:
## Gina is 25 year(s) old. ## Hector is 22 year(s) old.
## Number of people must equal number of ages!
## Provide at least one age!

4.3.9 Solutions to the Practice Exercises

Here’s a suitable program:
## [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427 3.000000 ## [10] 3.162278

You could do this:

Here you go:
doggies < c("Bo", "Gracie", "Rover", "Anya") titledDoggies < character(length(doggies)) for (i in 1:length(doggies) ) { titledDoggies[i] < paste(doggies[i], "the Dog") } titledDoggies
## [1] "Bo the Dog" "Gracie the Dog" "Rover the Dog" "Anya the Dog"

Here’s the code:
triangleOfStars < function(n) { for ( i in n:1 ) { line < rep("*", times = i) cat(line, "\n", sep = "") } }
Try it out:
triangleOfStars(5)
## ***** ## **** ## *** ## ** ## *

Here’s the code:

Here’s the code:
triangleOfStars < function(n) { while ( n >= 1 ) { line < rep("*", times = n) cat(line, "\n", sep = "") n < n  1 } }
Try it out:
triangleOfStars(5)
## ***** ## **** ## *** ## ** ## *

Here’s the code:
triangleOfStars < function(n) { m < 1 while ( m <= n ) { line < rep("*", times = m) cat(line, "\n", sep = "") m < m + 1 } }
Try it out:
triangleOfStars(5)
## * ## ** ## *** ## **** ## *****

Here is the requested annoying function, using a
repeat
loop withbreak
inside afor
loop: 
Here is one possibility:
ageReporter < function(people, ages) { ## validation: p < length(people) a < length(ages) if (p == 0) { return(cat("Provide at least one person!\n")) } if (a == 0) { return(cat("Provide at least one age!\n")) } if (!(p == a & p > 0)) { return(cat("Number of people must equal number of ages!\n")) } ## process: for (i in 1:length(people)) { cat(people[i], " is ", ages[i], " year(s) old.\n", sep = "") } }
4.4 Application: The Collatz Conjecture
Take any positive integer greater than 1. Apply the following rule, which we will call the Collatz Rule:
 If the integer is even, divide it by 2;
 if the integer is odd, multiply it by 3 and add 1.
Now apply the rule to the resulting number, then apply the rule again to the number you get from that, and so on.
For example, start with 13. We proceed as follows:
 13 is odd, so compute \(3 \times 13 + 1 = 40\).
 40 is even, so compute \(40/2 = 20\).
 20 is even, so compute \(20/2 = 10\).
 10 is even, so compute \(10/2 = 5\).
 5 is odd, so compute \(3 \times 5+ 1 = 16\)
 16 is even, so compute \(16/2 = 8\).
 8 is even, so compute \(8/2 = 4\).
 4 is even, so compute \(4/2 = 2\).
 2 is even, so compute \(2/2 = 1\).
 1 is odd, so compute \(3 \times 1 + 1 = 4\).
 4 is even, so compute \(4/2 = 2\).
 2 is even, so compute \(2/2 = 1\).
If we keep going, then we will cycle forever:
\[4, 2, 1, 4, 2, 1, \ldots\] In mathematics the Collatz Conjecture is the conjecture that for any initial positive number, every Collatz Sequence (the sequence formed by repeated application of the Collatz Rule) eventually contains a 1, after which it must cycle forever. No matter how large a number we begin with, we have always found that it returns to 1, but mathematicians do not know if this will be so for any initial number.
A sequence of Collatz numbers can bounce around quite remarkably before descending to 1. Our goal in this section is to write a function called collatz()
that will compute the Collatz sequence for any given initial number and draw a graph of the sequence as well.
First, let’s make a function just for the Collatz Rule itself:
(Recall that m %% 2
is the remainder of m
after it is divided by 2. If this is 0, then m
is even.)
Next let’s try to get a function going that will print out Collatz numbers:
collatz < function(n) {
# n is the initial number
while ( n > 1 ) {
cat(n, " ", sep = "")
# get the next number and call it n:
n < collatzRule(n)
}
}
Let’s try it out:
collatz(13)
## 13 40 20 10 5 16 8 4 2
So far, so good, but if we are going to graph the numbers, then we should store them in a vector. The problem is that we don’t know how long the vector needs to be.
One possible solution is to add to the vector as we go, like this:
collatz < function(n) {
numbers < numeric()
while ( n > 1 ) {
# stick n onto the end of numbers:
numbers < c(numbers, n)
n < collatzRule(n)
}
print(numbers)
}
Try it out:
collatz(13)
## [1] 13 40 20 10 5 16 8 4 2
This looks good. There are two problems, though, if the Collatz sequence happens to go on for a very long time.

Computation Time: the user doesn’t know when the sequence will end—if ever!—so she won’t know whether a delay in production of the output is due to a long sequence or a problem with the program itself. as the sequence gets longer, the computationtime is made even longer by the way the following line of code works:
numbers < c(numbers, n)
R cannot actually “stick” a new element onto the end of a vector. What it actually does is to move to a new place in memory and create an entirely new vector consisting of all the elements of
numbers
followed by the numbern
. R then assigns the namenumbers
to this value, freeing up the old place in memory where the previousnumbers
vector lived, but when a vector is very long copying can take a long time. Memory Problems Once the
numbers
vector gets long enough it will use all of the memory in the computer that is available to R. R will crash.
In order to get around this problem, we should impose a limit on the number of Collatz numbers that we will compute. We’ll set the limit at 10,000. The user can change the limit, but should exercise caution in doing so. Also, we’ll initialize our numbers
vector to have a length set to this limit. We can then assign values to elements of an already existing vector: this is much faster than copying entire vectors from scratch.
collatz < function(n, limit = 10000) {
# collatz numbers will go in this vector
numbers < numeric(limit)
# keep count of how many numbers we have made:
counter < 0
while ( n > 1 & counter < limit) {
# need to make a new number
counter < counter + 1
# put the current number into the vector
numbers[counter] < n
# make next Collatz number
n < collatzRule(n)
}
# find how many Collatz numbers we made:
howMany < min(counter, limit)
# print them out:
print(numbers[1:howMany])
}
Again let’s try it:
collatz(257)
## [1] 257 772 386 193 580 290 145 436 218 109 328 164 82 41 124 62
## [17] 31 94 47 142 71 214 107 322 161 484 242 121 364 182 91 274
## [33] 137 412 206 103 310 155 466 233 700 350 175 526 263 790 395 1186
## [49] 593 1780 890 445 1336 668 334 167 502 251 754 377 1132 566 283 850
## [65] 425 1276 638 319 958 479 1438 719 2158 1079 3238 1619 4858 2429 7288 3644
## [81] 1822 911 2734 1367 4102 2051 6154 3077 9232 4616 2308 1154 577 1732 866 433
## [97] 1300 650 325 976 488 244 122 61 184 92 46 23 70 35 106 53
## [113] 160 80 40 20 10 5 16 8 4 2
Things are working pretty well, but since the sequence of numbers might get pretty long, perhaps we should only print out the length of the sequence, and leave it to the reader to say whether the sequence itself should be shown.
collatz < function(n, limit = 10000) {
numbers < numeric(limit)
counter < 0
while ( n > 1 & counter < limit) {
counter < counter + 1
numbers[counter] < n
n < collatzRule(n)
}
howMany < min(counter, limit)
cat("The Collatz sequence has ", howMany, " elements.\n", sep = "")
show < readline("Do you want to see it (y/n)? ")
if ( show == "y" ) {
print(numbers[1:howMany])
}
}
Next let’s think about the plot. We’ll use the plotting system in the ggplot2 package (Wickham et al. 2020).
Later on we will make a serious study of plotting with ggplot2, but for now let’s just get the basic idea of plotting a set of points. First, let’s get a small set of points to plot:
xvals
contains the xcoordinates of our points, and yvals
contains the corresponding ycoordinates.
We set up a plot as follows:
The ggplot()
function sets up a basic twodimensional grid. The mapping
parameter explains how data will be “mapped” to particular positions on the plot. In this case it has been set to:
aes(x = xvals, y = yvals)
aes
is short for “aesthetics,” which has to do with how somethings looks. The expression means that xvals
will be located on the xaxis and yvals
will be located on the yaxis of the plot.
Now let’s see what we get if we actually run the call to the ggplot()
function (see Figure 4.2):
The plot is blank! Why is this? Well, although ggplot()
has been told what values are to be represented on the plot and where they might go, it has not yet been told how they should be shaped: it has not been told their geometry, you might say. We can add a geometry to the plot to get a picture (see Figure 4.3:
ggplot(mapping = aes(x = xvals, y = yvals)) +
geom_point()
The geometry determines a lot about the look of the plot. In order to have the points connected by lines we could add geom_line()
(see Figure 4.4:
ggplot(mapping = aes(x = xvals, y = yvals)) +
geom_point() +
geom_line()
We’ll choose a scatterplot with connecting lines for our graph of the sequence. With a little more work we can get nice labels for the x and yaxes, and a title for the graph. Our collatz()
function now looks like:
collatz < function(n, limit = 10000) {
# record initial number because we will change n
initial < n
numbers < numeric(limit)
counter < 0
while ( n > 1 & counter < limit) {
counter < counter + 1
numbers[counter] < n
n < collatzRule(n)
}
howMany < min(counter, limit)
steps < 1:howMany
cat("The Collatz sequence has ", howMany, " elements.\n", sep = "")
show < readline("Do you want to see it (y/n)? ")
if ( show == "y" ) {
print(numbers[steps])
}
# use initial value to make plot title:
plotTitle < paste0("Collatz Sequence for n = ", initial)
# make the plot
ggplot(mapping = aes(x = steps, y = numbers[steps])) +
geom_point() + geom_line() +
labs( x = "Step", y = "Collatz Value at Step",
title = plotTitle)
}
Try this version a few times, like so:
collatz(257)
It’s quite remarkable how much the sequence can rise and fall before hitting 1.
A further issue worth considering is that our collatz() function depends on the previouslydefined function collatzRule()
. In order for it to work correctly, R would need to be able to find the name collatzRule
somewhere on the search path. If the user hasn’t already defined the collatzRule()
function, then a call to `collatz() will fail.
One solution is simply to remind users of the need to define both collatzRule()
and collatz()
prior to running collatz()
. Another solution—perhaps the kinder one—is to define the collatzRule()
function in the body of collatz()
. Let’s adopt this approach.
The final version of the collatz()
function (with some validation thrown in for good measure) appears below.
collatz < function(n, limit = 10000) {
# add some validation:
n < suppressWarnings(as.integer(n))
isValid < !is.na(n) && n > 1
if (!isValid ) {
return(cat("Need an integer bigger than 1. Try again."))
}
# define collatzRule:
collatzRule < function(m) {
if ( m %% 2 == 0) {
return(m/2)
} else {
return(3*m + 1)
}
}
# On with the show!
# Record initial number because we will change it:
initial < n
numbers < numeric(limit)
counter < 0
while ( n > 1 & counter < limit) {
counter < counter + 1
numbers[counter] < n
n < collatzRule(n)
}
howMany < min(counter, limit)
cat("The Collatz sequence has ", howMany, " elements.\n", sep = "")
show < readline("Do you want to see it (y/n)? ")
if ( show == "y" ) {
print(numbers[1:howMany])
}
plotTitle < paste0("Collatz Sequence for n = ", initial)
steps < 1:howMany
ggplot(mapping = aes(x = steps, y = numbers[1:howMany])) +
geom_point() + geom_line() +
labs( x = "Step", y = "Collatz Value at Step",
title = plotTitle)
}
Glossary
 Flow Control

The collection of devices within a programming language that allow the computer to make decisions and to repeat tasks.
 Condition

A Boolean expression that commences an
if
orwhile
statement. If the condition evaluates toTRUE
, then the code in the body of the statement will be executed. Otherwise the code will be ignored.  Index Variable

The variable in a
for
loop that takes on each of the values of the iterable in succession.  Iterable

The vector that provides the sequence of values for the index variable in a
for
loop.  Validation

The process of checking user input and rejecting it—usually with helpful suggestions—if it is not of the correct form.
Exercises

The absolute value of a number \(x\) is defined to be the number \(x\) itself if \(x \ge 0\), whereas it is the opposite of \(x\) if \(x < 0\). Thus:
 the absolute value of 3 is 3;
 the absolute value of 3 is (3), which is 3;
 the absolute value of 5.7 is (5.7), which is 5.7
 the absolute value of 0 is 0.
The absolute value is important enough that R provides the
abs()
function to compute it. Thus:abs(3.7)
## [1] 3.7
Write a function called
absolute()
that computes the absolute value of any given numberx
. Your code should make no reference to R’sabs()
.Small Bonus: Write the function so that it follows the vectorin, vectorout principle, that is: when it is given a vector of numbers it returns the vector of their absolute values, like this:
vec < c(3, 5, 2.7) absolute(vec)
## [1] 3.0 5.0 2.7

Write a function called
pattern()
that, when given any character \(x\) and any positive number \(n\), will print the following pattern to the console: a line with just one \(x\),
 another line with two \(x\)’s,
 another line with three \(x\)’s,
 and so on until …
 a line with \(n\) \(x\)’s, and then
 another line with \(n1\) \(x\)’s,
 and so on until …
 a line with just one \(x\).
The function should take two arguments:

char
: the character to repeat. The default value should be"*"
. 
n
: the number of characters in the longest, middle line. The default value should be 3.
Typical examples of use should be as follows:
pattern()
## * ## ** ## *** ## ** ## *
pattern(char = "y", n = 5)
## y ## yy ## yyy ## yyyy ## yyyyy ## yyyy ## yyy ## yy ## y
Hint: You already know how to
cat
out a line consisting of any given number of a given character:char < "*" ## the desried character i < 4 ## the desired number of times cat(rep(char, times = i), "\n", sep = "")
## ****
You need to make a vector that contains the desired “number of times,” for each line. Consider this method:
n < 5 ## say we want 123454321 lineNumbers < c(1:(n1), n, (n1):1) lineNumbers
## [1] 1 2 3 4 5 4 3 2 1
Then you could write a
for
loop that iterates overlineNumbers
. 
Write a function called
checkerBoard()
that prints outs out checkerboard patterns like this:##  ## ***** ##  ## ***** ##  ## ***** ##  ## ***** ##  ## ***** ## 
The function should take two parameters:

char
, the character that fills the “squares” of the board. The default value should be"*"
. 
side
, the number of rows and columns of the board. There should be no default value.
Note that the horizontal boundaries are formed by the hyphen

and the vetical boundaries are formed by the pipe character
that appears on your keyboard above the backslash\
character.Typical examples of use should be as follows:
checkerBoard(char = "x", side = 3)
##  ## xxx ##  ## xxx ##  ## xxx ## 
Hint: Note that the number of hyphens in a boundary is always one more than twice the value of
side
. for example, suppose thatside
is 5. Then to get a row of the required hyphens, all you need is:## 
For a single row containing the character itself, you might try:
## xxxxx
In the example above, the value of
char
was"x"
. 

Write a function called
beerTune()
that prints out the complete lyrics to the song NinetyNine Bottles of Beer on the Wall. You’ll recall that the song goes like this:99 bottles of beer on the wall,
99 bottles of beer!
Take one down and pass it around:
98 bottles of beer on the wall.
98 bottles of beer on the wall,
98 bottles of beer!
Take one down and pass it around:
97 bottles of beer on the wall.
…
1 bottle of beer on the wall.
1 bottle of beer!
Take it down and pass it around:
No more bottles of beer on the wall.
Make sure to get the lyrics exactly right. For example, it’s “1 bottle,” not “1 bottles.”

Write a function called
farmSong()
that allows you to vary the lyrics the song about Old MacDonald’s Farm. The function should take two parameters:
animal
: a character vector of names of the animals on the farm; 
sound
: a character vector, of the same length as the vectoranimal
, giving the sound made by each creature inanimal
.
Neither parameter should have a default value. The function should validate its input, stopping with a helpful message if
animal
andsound
don’t have the same length.Typical examples of use should be as follows:
## Old MacDonald had a farm, eeieeioo! ## And on this farm he had a cow, eeieeioo! ## With a moomoo here and a moomoo there ## Here a moo, there a moo everywhere a moomoo, ## Old MacDonald had a farm, eeieeioo! ## ## Old MacDonald had a farm, eeieeioo! ## And on this farm he had a pig, eeieeioo! ## With a oinkoink here and a oinkoink there ## Here a oink, there a oink everywhere a oinkoink, ## Old MacDonald had a farm, eeieeioo!
## I need the same number of sounds as there are animals!
Note: As the above examples show, you don’t have to worry about getting “a” vs. “an” correct.


Recall the function
madhavaPI()
from Section 3.4.1. Use this function to write a function calledmadhavaSums()
that will do the following: given a number \(n\), the function returns a vector consisting of the first \(n\) approximations to \(\pi\), using the initial terms of the Madhava series. The function should take a single argumentn
, whose default value is 10. It should validate the input: if the number entered is not at least 1, then the function should explain to the user that the he/she must enter a positive number, and then stop.Here is an example of how the function should work:
madhavaSums(n = 3)
## You need to enter a positive integer. Try again!
Here is another example:
madhavaSums() # using the default value
## [1] 4.000000 2.666667 3.466667 2.895238 3.339683 2.976046 3.283738 3.017072 3.252366 ## [10] 3.041840
And another:
madhavaSums(n = 20)
## [1] 4.000000 2.666667 3.466667 2.895238 3.339683 2.976046 3.283738 3.017072 3.252366 ## [10] 3.041840 3.232316 3.058403 3.218403 3.070255 3.208186 3.079153 3.200366 3.086080 ## [19] 3.194188 3.091624

(*) The Subtraction Game. In this game there are two players, A and B, and a pile of \(n\) pebbles. The players take turns removing pebbles from the pile. On each turn, a player can take either one or two pebbles. The players who takes the last pebble wins the game.
It turns out that one of the players has a winning strategy. If the initial number of pebbles is a multiple of 3, then player who goes second has a winning strategy, whereas if the initial number of pebbles is not a multiple of 3 then the player who goes second has the winning strategy.
The idea for the winning strategy comes from the following observations:
 If there are 3 pebbles left and it’s the other player’s turn, then you will win. Why? Because after the other player removes pebbles there will be either 1 or 2 pebbles left. In either case you will be able to take the last pebble.
 If there are 6 pebbles left and it’s the other player’s turn, then you will win. Why? Because after the other player removes pebbles there will be either 4 or 5 pebbles left. In either case on your turn you will be able to reduce the number of pebbles to 3. The game is now in the state of the previous bullet item, where we know that you will win.
 If there are 9 pebbles left and it’s the other player’s turn, then you will win. Why? Because after the other player removes pebbles there will be either 7 or 8 pebbles left. In either case on your turn you will be able to reduce the number of pebbles to 6. The game is now in the state of the previous bullet item, where we know that you will win.
 And so on, for 12 left, 15 left, 18 left, etc.
As long as the number of pebbles left is a multiple of 3 and it’s the other player’s turn, you will win!
In this problem your task is to write a function called
subtraction()
that will play the Subtraction Game with a user. The function should take two parameters:
n
: the number of pebbles to begin with. The default value should be 12. 
userFirst
: a logical parameter that indicates whether the user or the computer plays first. The default value should beTRUE
, meaning that the user goes first.
Each time the computer plays it should announce how many pebbles it removed, and how many are left. When there are no pebbles left the computer should say who won and then quit the function.
The function should play optimally for the computer:
 if at the outset the computer has a winning strategy, then the computer should follow it and win.
 if at the outset the user has a winning strategy then the computer watch for opportunities to win if the user departs from her winning strategy.