class: 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[Iteration] ###
EMSE 4571: Intro to Programming for Analytics ###
John Paul Helveston ###
February 16, 2023 ] --- class: inverse # Quiz 3
10
:
00
.leftcol[ ## Write your name on the quiz! ## Rules: - Work alone; no outside help of any kind is allowed. - No calculators, no notes, no books, no computers, no phones. ] .rightcol[ <br> <center> <img src="https://github.com/emse-p4a-gwu/2022-Spring/raw/main/images/quiz_doge.png" width="400"> </center> ] --- # Common problems in homeworks -- ### .red[Use `almostEqual()` in test cases with numbers] -- This could fail: ```r stopifnot(getTheCents(2.45) == 45) ``` -- Instead, use: ```r stopifnot(almostEqual(getTheCents(2.45), 45)) ``` --- # Common problems in homeworks <br> ### .red[Check your full script for errors] - Restart R and run your whole code from the top - **Sequence matters**: Have you called a function before defining it? --- # Read homework feedback on Box ### Go to [box.com](https://box.com/) ### Search for folder named `netID-p4a` (e.g., `jph-p4a`) --- # Don't copy-paste code! <br> ## It's easy to catch (I use [this algorithm](https://theory.stanford.edu/~aiken/publications/papers/sigmod03.pdf)) ## Everyone involved gets a 0 --- class: inverse, middle # Week 5: .fancy[Iteration] ### 1. for loops ### 2. breaking and skipping ### BREAK ### 3. while loops --- class: inverse, middle # Week 5: .fancy[Iteration] ### 1. .orange[for loops] ### 2. breaking and skipping ### BREAK ### 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 ### 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 ``` ```r 10:1 ``` ``` #> [1] 10 9 8 7 6 5 4 3 2 1 ``` ]] --- # 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
## Your turn .font90[ 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`.<br>**Challenge**: Try solving this without a loop! - `sumOfOddsFromMToN(4, 10) == (5 + 7 + 9)` - `sumOfOddsFromMToN(5, 9) == (5 + 7 + 9)` ] --- class: inverse, middle # Week 5: .fancy[Iteration] .leftcol[ ### 1. for loops ### 2. .orange[breaking and skipping] ### BREAK ### 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
## Your turn `sumOfOddsFromMToNMax(m, n, max)`: Write a function that sums every _odd_ integer from `m` to `n` up until the sum is less than or equal to the value `max`. Your solution **must** 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[Iteration] .leftcol[ ### 1. for loops ### 2. breaking and skipping ### BREAK ### 3. .orange[while loops] ] .rightcol[ # Lame joke time: A friend calls her programmer roommate and said, "_while_ you're out, buy some milk"... ...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) { # Set stopping condition cat(i, '\n') * i <- i + 1 # Update condition } ``` ``` #> 1 #> 2 #> 3 #> 4 #> 5 ``` ] --- class: inverse
15
:
00
## Your turn: Write functions .leftcol[ The function `isMultipleOf4Or7(n)` 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[ Your job is to write `nthMultipleOf4Or7(n)`: 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
## Your turn .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/2023-Spring/hw/5-iteration.html) - ## Trickier turtles - ## Read about [Happy Numbers](https://en.wikipedia.org/wiki/Happy_number)