class: title-slide, middle, inverse .leftcol30[ <center> <img src="https://github.com/emse-p4a-gwu/emse-p4a-gwu.github.io/raw/master/images/p4a_hex_sticker.png" width=250> </center> ] .rightcol70[ # Week 5: .fancy[Loops] ### EMSE 4574: Intro to Programming for Analytics ### John Paul Helveston ### September 29, 2020 ] --- class: inverse # Quiz 3
10
:
00
.leftcol[ - ### Go to `#classroom` channel in Slack for link - ### Open up RStudio before you start - you'll probably want to use it. ] .rightcol[ <center> <img src="images/quiz_doge.png" width="400"> </center> ] --- # Notes on common problems in homeworks -- .leftcol[ ### Use `almostEqual()` in test cases with numbers This could fail on you: ```r stopifnot(getTheCents(2.45) == 45) ``` Instead, use: ```r stopifnot(almostEqual(getTheCents(2.45), 45)) ``` ] -- .rightcol[ ### Check your full script for errors - Restart R and run your whole code - **Sequence matters**: Have you called a function before defining it? ] --- class: middle, center ## Reconsidering productivity <center> <img src="images/productivity.png" width="500"> </center> --- class: inverse, middle # Week 5: .fancy[Loops] ## 1. for loops ## 2. breaking and skipping ## 3. while loops --- class: inverse, middle # Week 5: .fancy[Loops] ## 1. .orange[for loops] ## 2. breaking and skipping ## 3. while loops --- # "Flow Control" ### Code that alters the otherwise linear flow of operations in a program. -- .leftcol[ ### Last week: - `if` statements - `else` statements ] -- .rightcol[ ### This week: - `for` loops - `while` loops - `break` statements - `next` statements ] --- .leftcol[.code80[ # The `for` loop <br> ### Basic format: ```r for (item in sequence) { # Do stuff with item # Loop stops after last item } ``` ]] -- .rightcol[ ### Flow chart: <img src="images/loop_for.png" width="420"> ] --- # Making a sequence -- ### (Side note: these are vectors...that's next week - read ahead!) ### Two ways to make a sequence: -- .leftcol[.code80[ ### 1. Use the `seq()` function ```r seq(1, 10) ``` ``` ## [1] 1 2 3 4 5 6 7 8 9 10 ``` ```r seq(1, 10, by = 2) ``` ``` ## [1] 1 3 5 7 9 ``` ]] -- .rightcol[.code80[ ### 2. Use the `:` operator (step size = 1) ```r 1:10 ``` ``` ## [1] 1 2 3 4 5 6 7 8 9 10 ``` ]] --- # Sequences don't have to be integers -- Step size of 1: .code80[ ```r 1.5:5.5 ``` ``` ## [1] 1.5 2.5 3.5 4.5 5.5 ``` ] -- Step size of 0.4: .code80[ ```r seq(1.2, 6, 0.4) ``` ``` ## [1] 1.2 1.6 2.0 2.4 2.8 3.2 3.6 4.0 4.4 4.8 5.2 5.6 ## [13] 6.0 ``` ] --- # Quick code tracing
02
:
00
.leftcol[.code80[ What will this function print? ```r for (i in 1:5) { if ((i %% 2) == 0) { cat('--') } else if ((i %% 3) == 0) { cat('----') } cat(i, '\n') } ``` ]] --- # Quick code tracing
02
:
00
.leftcol[.code80[ What will this function print? ```r n <- 6 for (i in seq(n)) { cat('|') for (j in seq(1, n, 2)) { cat('*') } cat('|', '\n') } ``` ]] --- class: inverse
15
:
00
## Think-Pair-Share .font80[ 1) `sumFromMToN(m, n)`: Write a function that sums the total of the integers between `m` and `n`.<br>**Challenge**: Try solving this without a loop! - `sumFromMToN(5, 10) == (5 + 6 + 7 + 8 + 9 + 10)` - `sumFromMToN(1, 1) == 1` 2) `sumEveryKthFromMToN(m, n, k)`: Write a function to sum every kth integer from `m` to `n`. - `sumEveryKthFromMToN(1, 10, 2) == (1 + 3 + 5 + 7 + 9)` - `sumEveryKthFromMToN(5, 20, 7) == (5 + 12 + 19)` - `sumEveryKthFromMToN(0, 0, 1) == 0` 3) `sumOfOddsFromMToN(m, n)`: Write a function that sums every _odd_ integer between `m` and `n`. - `sumOfOddsFromMToN(4, 10) == (5 + 7 + 9)` - `sumOfOddsFromMToN(5, 9) == (5 + 7 + 9)` ] --- class: inverse, middle # Week 5: .fancy[Loops] .leftcol[ ## 1. for loops ## 2. .orange[breaking and skipping] ## 3. while loops ] .rightcol[ <img src="images/breaking.gif" width="400"> ] --- # Breaking out of a loop -- Force a loop to stop with `break` -- .leftcol[.code80[ **Note**: `break` doesn't require `()` ```r for (val in 1:5) { if (val == 3) { break } cat(val, '\n') } ``` ``` 1 2 ``` ]] --- # Quick code tracing
02
:
00
.leftcol[.code80[ What will this code print? ```r for (i in 1:3) { cat('|') for (j in 1:5) { if (j == 3) { break } cat('*') } cat('|', '\n') } ``` ]] --- # Skipping iterations -- Skip to the next iteration in a loop with `next` -- .leftcol[.code80[ **Note**: `next` doesn't require `()` ```r for (val in 1:5) { if (val == 3) { next } cat(val, '\n') } ``` ``` 1 2 4 5 ``` ]] --- # Quick code tracing
02
:
00
.leftcol[.code80[ What will this code print? ```r for (i in 1:3) { cat('|') for (j in 1:5) { if (j == 3) { next } cat('*') } cat('|', '\n') } ``` ]] --- class: inverse
15
:
00
## Think-Pair-Share `sumOfOddsFromMToNMax(m, n, max)`: Write a function that sums every _odd_ integer from `m` to `n` until the sum is less than the value `max`. Your solution should use both `break` and `next` statements. - `sumOfOddsFromMToNMax(1, 5, 4) == (1 + 3)` - `sumOfOddsFromMToNMax(1, 5, 3) == (1)` - `sumOfOddsFromMToNMax(1, 5, 10) == (1 + 3 + 5)` --- class: inverse, center # .fancy[Break]
05
:
00
--- class: inverse, middle # Week 5: .fancy[Loops] .leftcol[ ## 1. for loops ## 2. breaking and skipping ## 3. .orange[while loops] ] .rightcol[ # Lame joke time: A friend calls her programmer roommate and said, "while you're out, buy some milk"... ...and she never returned home. <img src="images/laugh_emoji.png" width="100"> ] --- .leftcol[ # The `while` loop ### Basic format: .code80[ ```r while (CONDITION) { # Do stuff here # Update condition } ``` ]] -- .rightcol[ Here's the general idea: <img src="images/loop_while.png" width="450"> ] --- # Quick code tracing
02
:
00
.leftcol[.code80[ Consider this function: ```r f <- function(x) { n <- 1 while (n < x) { cat(n, '\n') n <- 2*n } } ``` ]] .rightcol[.code80[ What will this code print? ```r f(5) f(10) f(50) f(60) f(64) ``` ]] --- ## `for` vs. `while` -- .leftcol[ ### Use `for` loops when the number of iterations is **_known_**. 1. Build the sequence 2. Iterate over it ```r *for (i in 1:5) { # Define the sequence cat(i, '\n') } ``` ``` ## 1 ## 2 ## 3 ## 4 ## 5 ``` ] -- .rightcol[ ### Use `while` loops when the number of iterations is **_unknown_**. 1. Define stopping condition 2. Iterate until condition is met ```r i <- 1 *while (i <= 5) { # Define stopping condition cat(i, '\n') * i <- i + 1 # Update condition } ``` ``` ## 1 ## 2 ## 3 ## 4 ## 5 ``` ] --- class: inverse
15
:
00
## Think-Pair-Share: Write functions .leftcol[ 1) `isMultipleOf4Or7(n)` Write a function that returns `TRUE` if `n` is a multiple of 4 or 7 and `FALSE` otherwise. - `isMultipleOf4Or7(0) == FALSE` - `isMultipleOf4Or7(1) == FALSE` - `isMultipleOf4Or7(4) == TRUE` - `isMultipleOf4Or7(7) == TRUE` - `isMultipleOf4Or7(28) == TRUE` ] .rightcol[ 2) `nthMultipleOf4Or7(n)` Write a function that returns the nth positive integer that is a multiple of either 4 or 7. - `nthMultipleOf4Or7(1) == 4` - `nthMultipleOf4Or7(2) == 7` - `nthMultipleOf4Or7(3) == 8` - `nthMultipleOf4Or7(4) == 12` - `nthMultipleOf4Or7(5) == 14` - `nthMultipleOf4Or7(6) == 16` ] --- class: inverse
20
:
00
## Think-Pair-Share .leftcol[ `isPrime(n)`: Write a function that takes a non-negative integer, `n`, and returns `TRUE` if it is a prime number and `FALSE` otherwise. Here's some test cases: - `isPrime(1) == FALSE` - `isPrime(2) == TRUE` - `isPrime(7) == TRUE` - `isPrime(13) == TRUE` - `isPrime(14) == FALSE` ] .rightcol[ `nthPrime(n)`: Write a function that takes a non-negative integer, `n`, and returns the nth prime number, where `nthPrime(1)` returns the first prime number (2). Hint: use the function `isPrime(n)` as a helper function! - `nthPrime(1) == 2` - `nthPrime(2) == 3` - `nthPrime(3) == 5` - `nthPrime(4) == 7` - `nthPrime(7) == 17` ] --- # [HW 5](https://p4a.seas.gwu.edu/2020-Fall/hw5-loops.html) -- - Trickier turtles -- - Read about [Happy Numbers](https://en.wikipedia.org/wiki/Happy_number) -- - Use the autograder