Programming in JuliaIteration
We have already seen one way of doing something to each element in a collection: the
smallest_factor = Dict(2 => 2, 3 => 3, 4 => 2, 5 => 5, 6 => 2, 7 => 7, 8 => 2, 9 => 3) [v for (k,v) in pairs(smallest_factor)]
In this array comprehension, we iterate over the pairs of the
The code above could also be rewritten as follows:
smallest_factor = Dict(2 => 2, 3 => 3, 4 => 2, 5 => 5, 6 => 2, 7 => 7, 8 => 2, 9 => 3) A =  for (k,v) in pairs(smallest_factor) push!(A,v) end A
for item in collection: works as follows: the first element of
collection is assigned to
item, and the block indented below the
for statement is executed. Then, the second element of
collection is assigned to
item, the indented block is executed again, etc., until the end of the collection is reached.
We can nest
for statements. For example, suppose we have a matrix represented as an array of arrays, and we want to sum all of the matrix entries. We can do that by iterating over the rows and then iterating over each row:
""" Return the sum of the entries of M """ function sum_matrix_entries(M) s = 0 for row in M for entry in row s = s + entry end end s end using Test M = [[1,2,3],[4,5,6],[7,8,9]] @test sum_matrix_entries(M) == 45
Suppose you have imported a function
file_bug_report with two parameters:
description. Suppose also that you have a
bugs whose keys are ids and whose values are strings representing descriptions. Write a loop which performs the action of filing each bug report in the dictionary.
"A dummy function which represents filing a bug report" function file_bug_report(id, description) println("bug $id ($description) successfully filed") end bugs = Dict( "07cc242a" => "`trackShipment` hangs if `trackingNumber` is missing", "100b359a" => "customers not receiving text alerts" )
Solution. We loop over the pairs of the dictionary:
for (id, desc) in pairs(bugs) file_bug_report(id, desc) end
sumorial which takes a positive integer
n as an argument and sums of the integers 1 to
n using a loop.
"Return the sumorial of a positive integer n" function sumorial(n) # add code here end using Test @test sumorial(3) == 6 @test sumorial(8) == 36 @test sumorial(200) == 20100
Solution. We loop through
1:n and add as we go.
function sumorial(n) total = 0 for k in 1:n total = total + k end total end using Test @test sumorial(3) == 6 @test sumorial(8) == 36 @test sumorial(200) == 20100
The Collatz conjecture is one of the easiest-to-state unsolved problems in mathematics. Starting from any given positive integer, we halve it if it's even and triple it and add one if it's odd. The Collatz conjecture states that repeatedly applying this rule always gets us to the number 1 eventually. For example, the Collatz sequence starting from 17 is
17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1
If we want to write a Julia function which returns the Collatz sequence for any given starting number, we face a problem: we don't know from the start how many steps it will take to reach 1, so it isn't clear how we could use a for loop. What we want to do is execute a block of code until a given condition is met. Julia provides the
while loop for this purpose.
"Return the Collatz sequence starting from n" function collatz_sequence(n) sequence = [n] while n > 1 if n % 2 == 0 n = n ÷ 2 else n = 3n + 1 end push!(sequence,n) end sequence end using Test @test collatz_sequence(17) == [17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
The expression which appears immediately following the
while keyword is called the condition, and the block indented below the
while statement is the body of the loop. The rules of the language stipulate the following execution sequence for a
while statement: the condition is evaluated, and if it's true, then the body is executed, then condition is evaluated again, and so on. When the condition returns
false, the loop is exited. An exit can also be forced from within the body of the while loop with the keyword
Newton's algorithm for finding the square root of a number
n starts from 1 and repeatedly applies the function . For example, applying this algorithm to approximate , we get
1, 3/2, 17/12, 577/408, ...
This algorithm converges very fast: 577/408 approximates with a relative error of about 0.00015%.
Write a function
newtonsqrt which takes as an argument the value
n to square root and applies Newton's algorithm until the relative difference between consecutive iterates drops below .
Note that can be represented in Julia using scientific notation
function newtonsqrt(n) """Use Newton's algorithm to approximate √n""" # add code here end using Test @test abs(newtonsqrt(2) - 1.4142135623730951) < 1e-6 @test abs(newtonsqrt(9) - 3) < 1e-6
Solution. We keep up with two separate variables, which we call
old_x, to compare the most recent two iterates:
"""Use Newton's algorithm to approximate √n""" function newtonsqrt(n) x = 1 while true old_x = x x = 1/2 * (x + n/x) if abs(x - old_x)/old_x < 1e-8 return x end end end
Write a function which prints an checkerboard pattern of
\n in a string literal represents the "newline" character. You'll need to print this character after each row you've printed.
""" Prints an n × n checkerboard, like: xoxo oxox xoxo oxox """ function checkerboard(n) # add code here end
Solution. We loop through the rows and use an
if statement to print a different output depending on whether the row is even-numbered or odd-numbered.
"Prints an n × n checkerboard" function checkerboard(n) for i in 1:n if iseven(i) print("xo" ^ (n÷2)) else print("ox" ^ (n÷2)) end print("\n") end end
Write a function which prints Pascal's triangle up to the $n$th row, where the top row counts as row zero. You might want to use a helper function
print_row(n,row) to manage the responsibility of printing each row, as well as a helper function
next_row(row) to calculate each row from the previous one.
Example output, for
n = 4:
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1
Note: there's no solution to this one, but you can do it on your own!
""" Prints the nth row (`row`) of Pascal's triangle with appropriate spacing. """ function print_row(n,row) # add code here end """ Returns the next row in Pascal's triangle. Example: next_row([1,3,3,1]) == [1,4,6,4,1] """ function next_row(row) # add code here end """ Print the first n rows of Pascal's triangle """ function pascals_triangle(n) # add code here end