Exercises

1. 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 number x. Your code should make no reference to R’s abs().

Small Bonus: Write the function so that it follows the vector-in, vector-out 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
2. 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 $$n-1$$ $$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 1-2-3-4-5-4-3-2-1
lineNumbers <- c(1:(n-1), n, (n-1):1)
lineNumbers
## [1] 1 2 3 4 5 4 3 2 1

Then you could write a for-loop that iterates over lineNumbers.

3. 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)
## -------
## |x|x|x|
## -------
## |x|x|x|
## -------
## |x|x|x|
## -------

Hint: Note that the number of hyphens in a boundary is always one more than twice the value of side. for example, suppose that side is 5. Then to get a row of the required hyphens, all you need is:

boundary <- c(rep("-", times = 2 * side + 1), "\n")
cat(boundary, sep = "")
## -----------

For a single row containing the character itself, you might try:

between <- c("|", rep(c(char, "|"), times = side), "\n")
cat(between, sep = "")
## |x|x|x|x|x|

In the example above, the value of char was "x".

4. Write a function called beerTune() that prints out the complete lyrics to the song Ninety-Nine 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”.

5. 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 vector animal, giving the sound made by each creature in animal.

Neither parameter should have a default value. The function should validate its input, stopping with a helpful message if animal and sound don’t have the same length.

Typical examples of use should be as follows:

farmSong(animal = c("cow", "pig"), sound = c("moo", "oink"))
## Old MacDonald had a farm, ee-i-ee-i-oo!
## And on this farm he had a cow, ee-iee-i-oo!
## With a moo-moo here and a moo-moo there
## Here a moo, there a moo everywhere a moo-moo,
## Old MacDonald had a farm, ee-i-ee-i-oo!
##
## Old MacDonald had a farm, ee-i-ee-i-oo!
## And on this farm he had a pig, ee-iee-i-oo!
## With a oink-oink here and a oink-oink there
## Here a oink, there a oink everywhere a oink-oink,
## Old MacDonald had a farm, ee-i-ee-i-oo!
farmSong(animal = c("cow", "pig", "horse"), sound = c("moo", "oink"))
## 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.

6. Recall the function madhavaPI() from Section 3.4.1. Use this function to write a function called madhavaSums() 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 argument n, 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
##  [8] 3.017072 3.252366 3.041840

And another:

madhavaSums(n = 20)
##  [1] 4.000000 2.666667 3.466667 2.895238 3.339683 2.976046 3.283738
##  [8] 3.017072 3.252366 3.041840 3.232316 3.058403 3.218403 3.070255
## [15] 3.208186 3.079153 3.200366 3.086080 3.194188 3.091624
7. (*) 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 be TRUE, 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.