1 February 2022

Convert Overnight some submissions have arrived in Canvas. Let's open some and take a look. You can download them in .zip or .tar format.

Looking at the submissions, we could see that there were some inefficiencies. One item of interests: you need to know how to use list comprehensions. We show an example here.

List Comprehensions Some of you don't know about this. Corey Shafer's Video will fill you in. Watch it. Here is an example.


>>> x = [2,5,7,2,9,5]
>>> y = [k*k for k in x]
>>> y
[4, 25, 49, 4, 81, 25]
>>> z = [k*k for k in x if k*k*k < 200]
>>> z
[4, 25, 4, 25]

Don't do this.


>>> out = []
>>> for k in x:
...     if k*k*k < 200:
...             out.append(k*k)
... 
>>> 

The Weierstraß Intermediate Value Theorem

Theorem Suppose that f is a continuous function defined on the interval [a,b]. If y is any value between a and b, then there is some x ∈ [a,b] so that f(x) = y.

This is an existence theorem, but it can be used to develop an algorithm for approximating a root of a function.

picture illustrating the Intermediate Value Theorem

The graph of f must cross the horizontal line at y.

Suppose we want to compute \(\sqrt{2}\). It is very easy to see that the function \(f(x) = x^2 - 2\) has \(\sqrt{2}\) as a root. Since \(f(1) = -1\) and \(f(2) = 2\), the intermediate value theorem tells us that \(f\) must have a root in the interval \([1, 2]\). We can approximate this root with \(1.5\) with a greatest possible error of $\(\pm .5\)$.

Next, compute \(f(1.5) = .25\). Since \(f(1) \lt 0\), the function \(f\) changes sign on \([1, 1.5]\). We have are close to a root at 1.25 with error \(\pm .25\).

You can continue in this fashion until the error is as small as you wish, since the error halves with each iteration.

You will implement this algorithm in zero_finder.py.

A Little Number Theory

Divisibility Much of number theory revolves around the divisibility and factorization of integers. This apparatus has far-reaching applications in cryptography.

Definition We write d | a, and say "d divides a" if some integer q, a = d*q. We can test for this in in Python, Java, C, or JS using a%d == 0.

Here is an interesting question. If d | a and d | b, what else is divisible by d?

This is true for certain, per zhang22b: d*d | ab.

We also have this: d | a + b.

Let's prove it.

We can write Write a = d*q for some integer q, and we can write b = d*r for some integer r. Then

a + b = d*(q + r);

since q + r is an integer, d | a + b.

Next we ask: What divides zero evenly? Every integer divides 0!

Here's something even more useful.

Suppose that x and y are integers. Then, using what we wrote above we have

a*x + b*y = d*q*x + d*r*y = d*(q*x + r*y).

We can conclude that

d | a*x + b*y

The gcd Function

For integers a and b that are not both 0, we define gcd(a,b) to be the greatest common divisor of a and b. Note that 1 is a common divisor of any two integers, and that no divisor of a and b is larger than max(a,b), so this thing exists.

Note that gcd(0,0) is not defined, because 0 is divisible by every integer.

If you are writing this function, you need to do this.

Reminder: Exceptions in Java

Here is the Throwable subtree.



         ----------------
         |  Throwable   |
         ----------------
        /               \
  ------------     -------------
  | Error    |     | Exception |
  ------------     -------------
      |                  |
    DEATH          --------------------
                   | RuntimeException |
                   --------------------

Theorem Suppose b, q, a and r are integers and that b = a*q + r. then gcd(a, b) = gcd(a, r).

Proof. Suppose d | a and d|b. Then d | b - a*q. So, d|r. d is common divisor of a and r.

Suppose d | a and d | r. Then d | a*q + r. So d|b. Every common divisor of a and r is a common divisor of a and b.

QED

Here we use the theorem to compute a gcd.

By our theorem, all of the things in the first column are equal.

gcd(528, 341)           528%341 = 187    528 = 341(1) + 187
gcd(187, 341)           341%187 = 154    341 = 187(1) + 154
gcd(187, 154)           187%154 = 33     187 = 154(1) + 33
gcd(154,33)             154%33 = 22      154 =  33(4) + 22
gcd(22,33)              33%22 = 11        33 =  22(1) + 11
gcd(22,11)              22%11 = 0         22 =  11(2) + 0
gcd(11, 0) = 11

Turtle Problem Can you think of a case where this is slow as possible?? Bounty: 10 point bonus for first correct written answer.

Bezout's Theorem If a and b are integers not both zero, then there are integers x and y so that

ax + by = gcd(a,b).

There is a proof in numbers.pdf that uses the well-ordering principle on the positive integers.

To actually compute these coefficients, you must back-substitute in the chain shown above. You are going to write a program bezout.py that does this. It's a royal pain in the keister. Quoth my old friend Judith Anne Raphael, "It's big and it's yours."

The Division Algorithm

Primality