Computer Science 121

Computer Science 121
Scientific Computing
Winter 2016
Chapter 8
Loops
Loops: Motivation
• We've already seen algorithms (findsmallest, Fibonacci, factorial) that repeat
the same steps over and over
• Without an explicit “repeat” instruction,
this becomes tedious and error-prone.
• Example: computing a square root
Square Root Algorithm:
Basic Idea
• The square root of x must lie somewhere
between 0 and x : i.e., 0 is its lower bound, and x
is its upper bound.
• “Somewhere between” is vague, so we'll define it
as “halfway between”: add the lower bound and
upper bound and divide by 2, to approximate √x.
• If our approximation is too big, lower the upper
bound; if too small, raise the lower bound.
• The more we repeat this, the closer we get to √x.
Square Root Algorithm:
“Pseudocode”
1) Lower = 0; Upper = x
2) Repeat until happy:
3)
S = (Upper + Lower) / 2
4)
If S2 > x, let Upper = S (was too big!)
5)
Otherwise Lower = S (was too small!)
6) Report S
Square Root Algorithm:
Example: Compute √2
Lower = 0; Upper = 2
S = (0+1)/2 = 1
12 = 1, so too small: Lower = 1
Lower = 1; Upper = 2
S = (1+2)/2 = 1.5
1.52 = 2.25, so too big: Upper = 1.5
Lower = 1; Upper = 1.5
S = (1+1.5)/2 = 1.25
1.252 = 1.5625, so too small: Lower = 1.25
Lower = 1.25; Upper = 1.5
S = (1.25+1.5)/2 = 1.375
1.3752 = 1.891, so too small: Lower = 1.375
etc.
Does this work
for any positive
number n ?
Square Root Algorithm:
Upgrade for 0 < x < 1
1) If n < 1: Lower = x; Upper = 1
2) Otherwise: Lower = 0; Upper = x
3) Repeat until happy:
4)
S = (Upper + Lower) / 2
5)
If S2 > x, let Upper = S (was too big!)
6)
Otherwise Lower = S (was too small!)
7) Report S
Square Root Algorithm:
Python at Last!
def mysqrt(x):
if x < 1:
lower = x
upper = 1
else:
lower = 0
upper = x
for k in range(1000): # 1000 reps get us pretty close!
s = (lower+upper)/2
if s**2 > x:
upper = s
else:
lower = s
return s
for loops: general syntax
• List of values is usually range(n),
where n = some large number
• Variable name is sometimes a "dummy":
(not used)
• range is like NumPy arange
for loops: non-numerical example
•def grumpyCat(names):
•for name in names:
•print("I hate " + name)
•
•>>> grumpyCat(["Joe", "Sally", "Fred"])
•I hate Joe
•I hate Sally
•I hate Fred
8.2 Accumulators
• Of ourse, we'd use the built-in sum
function in a real program
• But understanding the general pattern of
accumulators is important
Accumulators
• Anything that reduces an array of values to
a single value is an accumulator
• So: sum, prod, min, max, mean,
stdev, ...
8.3 Nested Loops
• Any code we like can be inside a loop:
including another loop!
• Example: Let's write a function that
computes the probability of rolling a
certain sum in pair of dice:
8.3 Nested Loops
• Any code we like can be inside a loop:
including another loop!
• Example: Let's write a function that
computes the probability of rolling a
certain sum in pair of dice:
• Can we use our NumPy Fu to do this without
loops?
8.4 Nested Loops: Optimal Job
Matching
• Four people, four tasks
• One person per task at a
given time
• Each person is better at
some tasks, worse at others
• Represent an assignment of tasks as an array, e.g.:
[2,1,4,3] = Alison on 2, Basil on 1, Clyde on 4, Daisy on 3
• Do an exhaustive search of all assignments to
find the best outcome
How about this?
Exclude Impossible Assignments,
via set
Can we do it in a more general way?
from itertools import permutations
from numpy import *
def matchpeople(q):
# number of people (jobs)
n = len(q)
jobs = arange(n)
bestassignment = []
bestqualitysofar = 0
for assignment in permutations(jobs):
totalquality = 0
for j in range(n):
k = assignment[j]
totalquality += q[j][k]
if totalquality > bestqualitysofar:
bestqualitysofar = totalquality
bestassignment = assignment
return bestassignment
8.5 Element-by-Element operations
>>> from numpy import *
>>> a = array([1,2,3,4,5])
>>> mysqrt(a)
Traceback (most recent call last):
blah blah blah
ValueError: The truth value of an array with
more than one element is ambiguous. Use
a.any() or a.all()
>>> mysqrtv = vectorize(mysqrt)
>>> mysqrtv(a)
array([ 1., 1.41421, 1.73205, 2., 2.23606])
8.6 Outputs of unknown size
• Size of a function's output isn't always the
same as (or directly related to) its input
• Example: translate ASCII text to Morse
code (use 1 for dot , 2 for dash, .etc.)
http://morsecode.scphillips.com/translator.html
8.6 Outputs of unknown size
• Solution: start with [] and use append
• How would we write charToMorse() ?
8.7 Loop Termination
• Sometimes we should break out of a loop before
it's done:
• Can you think of slightly shorter version?
8.8 Conditional Looping with while
• Sometimes we don't even know how many times to loop
• Classic example: Compute the prime factors of a
number n