cs111 Coursepack 20fall
cs111 Coursepack 20fall
Course Overview
Welcome to CS 111!
Computer science is not so much the science of computers
as it is the science of solving problems using computers.
Eric Roberts
• Main goals:
• to develop your computational problem-solving skills
• including, but not limited to, coding skills
• to give you a sense of the richness of computer science
A Rigorous Introduction
• Intended for:
• CS, math, and physical science concentrators
• others who want a rigorous introduction
• no programming background required,
but can benefit people with prior background
Course Website
www.cs.bu.edu/courses/cs111
Grading
1. Weekly problem sets + final project (45%)
2. Exams
• online with two time options (see syllabus)
• may require you to use a webcam and microphone
• access to cell phone with data plan recommended
• two midterms (25%)
• final exam (25%)
• wait until you hear its dates/times from me;
initial info posted by Registrar will likely be incorrect;
make sure you're available for the entire exam period!
3. Pre-lecture quizzes (5%)
• full credit if you answer 85% of the questions (see syllabus)
• Office-hour calendar:
http://www.cs.bu.edu/courses/cs111/office_hours.shtml
Programming
• Programming involves expressing an algorithm in a form that
a computer can interpret.
Scratch
• A simple but powerful graphical programming language
• developed at the MIT Media Lab
• makes it easy to create animations, games, etc.
• Sprites perform actions and interact with each other on the stage.
the stage
building
blocks
for
programs/
scripts
Flow of Control
• Flow of control = the order in which statements are executed
forms
• To create a variable:
note: you must drag a variable into place, not type its name
• Boolean operators:
• They have an input area with pointed edges for the condition.
• Examples:
>>> 6 * 7
42
>>> 2 ** 4
16
>>> 17 % 2
1
>>> 17 % 3
_________
• Examples:
>>> 2 + 3 * 5
___________
>>> (2 + 3) * 5
___________
• Examples:
Variables
• Variables allow us to store a value for later use:
>>> temp = 77
>>> (temp - 32) * 5 / 9
25.0
• They include:
• literals ("hard-coded" values):
3.1416
'Picobot'
• variables
temp
• combinations of literals, variables, and operators:
(temp - 32) * 5 / 9
quarters = 2
dimes = 3
nickels = 1
pennies = 4
cents = quarters*25 + dimes*10 + nickels*5 + pennies
print('you have', cents, 'cents')
Assignment Statements
• Assignment statements store a value in a variable.
temp = 20
= is known as the
• General syntax: assignment operator
variable = expression
• Steps:
1) evaluate the expression on the right-hand side of the =
2) assign the resulting value to the variable on the
left-hand side of the =
• Examples:
int quarters = 10
quarters_val = 25 * quarters
int 25 * 10
int 250
• Example:
num1 = 100
num2 = 120 num1 100 num2 120
• Example:
sum = 13
val = 30 sum 13 val 30
• Basic syntax:
print(expr)
or
print(expr1, expr2, … exprn)
where each expr is an expression
• second example:
cents = 89
print('you have', cents, 'cents')
output: _________________________
'Perry'
• from right to left, starting from -1
-5 -4 -3 -2 -1
'Perry'
• 'P' has an index of 0 or -5
• 'y' has an index of ____________
>>> s[0:8:2]
'bso ' # note the space at the end!
Skip-Slicing (cont.)
• Slices can have a third number: string [start : end : stride_length ]
>>> s[5:0:-1]
____________
x = 15
name = 'Picobot'
x = x // 2
print('name', x, type(x))
x = 15
name = 'Picobot'
x = 7.5
print(name, 'x', type(x))
s = ('d' * 3) + s
s = s[2:-2]
Skip-Slicing
• Slices can have a third number: string [start : end : stride_length ]
>>> s[0:8:2]
'bso ' # note the space at the end!
>>> s[5:0:-1]
'notso'
>>> s[ : : ] # what numbers do we need?
'viti'
>>> s[12:21:8] + s[21::3] # what do we get?
Lists
• Recall: A string is a sequence of characters.
'hello'
• For a list:
• slicing produces a list
• indexing produces a single element – may or may not be a list
>>> info = ['Star Wars', 1977, 'PG', [35.9, 460.9]]
>>> info[1:2] >>> info[2:]
[1977] ___________________
>>> info[1] >>> info[-1][-1]
1977 460.9
>>> info[-1] >>> info[0][-4]
___________________ ___________________
Defining a Function
the function's name x is the input or parameter
def triple(x):
return 3*x
this line specifies what
the function outputs (or returns)
must indent – in this case, 3 times the input
print(calculate(3, 2))
print(calculate(3, 2))
• For a list:
• slicing produces a list
• indexing produces a single element – may or may not be a list
>>> info = ['Star Wars', 1977, 'PG', [35.9, 460.9]]
>>> info[1:2] >>> __________________
[1977] 35.9
>>> info[1]
1977
>>> info[-1]
[35.9, 460.9]
dgs_courses = _______________________
A. intro_cs[2:3] + intro_cs[-1:]
B. intro_cs[-4] + intro_cs[5]
C. intro_cs[-4] + intro_cs[-1:]
def redo(s):
""" Adds the prefix "re" to the input s. """
return 're' + s
• Examples:
>>> undo('plugged')
>>> undo('zipped')
>>> redo('submit')
>>> redo(undo('zipped'))
print(calculate(4, 1))
def avg_first_last(values):
first = _____________
last = _____________
return _______________
Part 1 Part 2
Conditional Execution
• Conditional execution allows your code to decide whether
to do something, based on some condition.
• example:
def abs_value(x):
""" returns the absolute value of input x """
if x < 0:
x = -1 * x
return x
• Example:
def abs_value(x):
if x < 0:
x = -1 * x # true block
return x
• Example:
def pass_fail(avg):
if avg >= 60:
grade = 'pass' # true block
else:
grade = 'fail' # false block
return grade
== equal to total == 10
(don't confuse with = ) letter == 'P'
def welcome(class):
if class == 'frosh':
print('Welcome to BU!')
print('Have a great four years!')
else:
print('Welcome back!')
print('Have a great semester!')
print('Be nice to the frosh students.')
• example:
>>> letter_grade(95)
_______________
• example:
>>> letter_grade(95)
_______________
true
condition1 true block 1
false
true
condition2 true block 2
false
...
false
false block
next statement
• Python example:
if x < 0:
print('x is negative')
x = -1 * x
• Python example:
if x < 0:
print('x is negative')
x = -1 * x
else:
print('x is positive')
def welcome(class):
if class == 'frosh':
print('Welcome to BU!')
print('Have a great four years!')
else:
print('Welcome back!')
print('Have a great semester!')
print('Be nice to the frosh students.')
def welcome(class):
if class == 'frosh':
print('Welcome to BU!')
print('Have a great four years!')
else:
print('Welcome back!')
if class == 'senior':
print('Have a great last year!')
else:
print('Have a great semester!')
print('Be nice to the frosh students.')
print(mystery(0, 5))
print(mystery(0, 5))
Local Variables
def mystery(x, y):
b = x - y # b is a local var of mystery
return 2*b # we can access b here
c = 7
mystery(5, 2)
print(b + c) # we can't access b here
c = 7 # c is a global variable
mystery(5, 2)
print(b + c) # we can access c here
b = 1 # this b is global
c = 7
mystery(5, 2)
print(b + c) # we access the global b here
• The pale arrow shows the line that was just executed.
diagram from:
math.about.com
import math
dist = distance(2, 3, 5, 7)
print('distance between (2, 3) and (5, 7) is', dist)
x = 8
mystery2(3, 2)
print(x)
x = 8
mystery2(3, 2)
print(x)
y = 8
quadruple(y)
print(y)
y = 8
quadruple(y)
print(y)
g frame for 2nd call
x =
return -1 * x
x = 2
y = 0 global
x | y
y = foo(y, x)
print(x, y)
foo(x, x)
print(x, y) output
print(foo(x, y))
print(x, y)
else:
rest = fac(n – 1)
return n * rest
fac(5) n:
rest:
return value:
fac(4) n:
rest:
return value:
fac(3) n:
rest:
return value:
fac(2) n:
rest:
return value:
fac(1) n:
rest:
return value:
• Do one step!
• use s[0] to access the initial element
• do something with it
else:
• Ask yourself:
(base case) When can I determine the length of s without
looking at a smaller string?
(recursive How could I use the length of anything smaller
substructure) than s to determine the length of s?
mylen('ow')
s =
len_rest =
return 4 different
stack frames,
each with its own
s and len_rest
else:
• Ask yourself:
p
(base case) When can I determine b without determining
a smaller power?
(recursive How could I use anything smaller than bp
substructure) to determine bp?
power(3, 2)
b = 3, p = 2
pow_rest =
return 4 different
stack frames,
each with its own
b, p and pow_rest
foo
Tracing Function Calls (cont.) x | y
0 2
def foo(x, y): 3 3
y = y + 1
x = x + y
print(x, y)
return x
x = 2
y = 0 global
x | y
y = foo(y, x) 2 0
print(x, y) 2 3
foo(x, x)
print(x, y) output
3 3
print(foo(x, y)) 2 3
print(x, y)
You specify
one step
at the end.
print(mylen('step'))
def mylen(s):
mylen('step') if s == '':
s = 'step'
return 0
len_rest = mylen('tep')
else:
len_rest = mylen(s[1:])
mylen('tep')
s = 'tep' return len_rest + 1
len_rest = mylen('ep')
mylen('ep')
s = 'ep'
len_rest = mylen('p') Fill in the rest
of the stack frames!
A Recursive Warning!
Hofstadter’s Law:
It always takes longer than you think it will take,
even when you take into account Hofstadter’s Law.
aliens rejoice
num_vowels('aha')
num_vowels('aha')
s = 'aha'
num_rest = ??
num_vowels( )
s =
num_rest =
• examples:
>>> mymax([5, 8, 10, 2])
10
>>> mymax([30, 2, 18])
30
1. compare the first element to largest element in the rest of the list
2. return the larger of the two
Let the recursive call handle the rest of the list!
• examples:
>>> mymax([5, 8, 10, 2])
result: 10
>>> mymax([30, 2, 18])
result: 30
mymax( )
vals =
max_rest = mymax(__________)
result: ____________
s1 = 'always' s2 = 'recurse!'
replace(s1, 'a', 'o') replace(s2, 'e', 'i')
= =
• Examples:
>>> list(range(3, 10))
[3, 4, 5, 6, 7, 8, 9]
>>> list(range(8))
________________________________
• In particular, we can:
• pass a function as an input to another function
• return a function as the result of another function
map()
• A higher-order function
• Syntax:
map(function, sequence)
• As with range:
• you can think of map as producing a list
• in many cases it can be used like one
• to see the actual list, we need to use map with list
def square(x):
return x*x
def first_char(s):
return s[0]
________________________________
List Comprehensions
The same as map, only better!
• Recall:
def triple(x):
return 3*x
Examples of LCs
[1, 2, 3, 4]
>>> [111*n for n in range(1, 5)]
[111, 222, 333, 444]
_____________________
• Syntax:
[expression for variable in sequence]
or
[expression for variable in sequence if boolean]
• Examples:
[0, 1, 2, 3, 4, 5]
>>> [2*x for x in range(6) if x % 2 == 0]
[0, 4, 8]
__________________________
def square(x):
return x*x
def first_char(s):
return s[0]
print(lc)
# using an LC
def mylen(seq):
lc = [1 for x in seq]
return sum(lc)
# here's a one-liner!
def mylen(seq):
return sum([1 for x in seq])
# using an LC
def num_vowels(s):
lc = [1 for c in s if c in 'aeiou']
return sum(lc)
# here's a one-liner!
def num_vowels(s):
return sum([1 for c in s if c in 'aeiou'])
def num_odds(values):
""" returns the number of odd #s in a list
input: a list of 0 or more integers
"""
lc = ____________________________________
return sum(lc)
remove_vowels('recurse')
s = 'recurse'
rem_rest = ??
remove_vowels()
def remove_vowels(s):
""" returns the "vowel-less" version of s
input s: an arbitrary string
"""
if s == '':
return ''
else:
rem_rest = remove_vowels(s[1:])
# do our one step!
if s[0] in 'aeiou':
return ________________
else:
return ________________
rem_all()
def rem_all(elem, values):
""" removes all occurrences of elem from values
"""
if values == []:
return _______
else:
rem_rest = rem_all(______, ________)
if ________________:
return ________________
else:
return ________________
_______________
_______________________
def shortest_word(words):
""" returns the shortest word from the input
list of words
"""
scored_words = [[len(w), w] for w in words]
min_pair = min(scored_words)
return min_pair[1]
ASCII
American Standard Code for Information Interchange
'a' 97
'b' 98
'c' 99
...
values
ABCDEFGHIJKLMNOPQRSTUVWXYZ
65 67 69 71 73 75 77 79 81 83 85 87 90
Encryption
abcdefghijklmnopqrstuvwxyz
• Example: a shift of 3
'a' 'd' 'A' 'D'
'b' 'B'
'c' 'C'
etc.
original message encrypted message
'my password is foobar' 'pb sdvvzrug lv irredu'
values
ABCDEFGHIJKLMNOPQRSTUVWXYZ
65 67 69 71 73 75 77 79 81 83 85 87 90
• ord() and addition gives the ASCII code of the shifted letter:
>>> ord('b')
98
>>> ord('b') + 3 # in general, ord(c) + shift
101
result: 596.0
• Assume we have:
• a list of possible Scrabble words
words = ['aliens', 'zap', 'hazy', 'code']
• a scrabble_score() function like the one from PS 2
best_word()
def best_word(words):
""" returns the word from the input list of words
with the best Scrabble score
"""
scored_words = [[scrabble_score(w), w] for w in words]
bestpair = max(scored_words)
return bestpair[1]
abcdefghijklmnopqrstuvwxyz
• Example: a shift of 3
'a' 'd'
return _______________
Helper Functions
• When designing a function, it often helps to write a
separate helper function for a portion of the overall task.
• We've seen this before:
• scrabble_score() called letter_score()
def letter_score(letter):
if letter in 'aeilnorstu':
return 1
...
def scrabble_score(word):
if ...
...
else:
score_rest = scrabble_score(...)
return letter_score(...) + ...
• Examples:
• jscore('diner', 'syrup') 1
• jscore('always', 'bananas') 3
• jscore('always', 'walking') 3
• rem_first(elem, values)
• inputs: an arbitrary value (elem) and a list (values)
• returns: a version of values in which only the first
occurrence of elem in values (if any) is removed
if values[0] == elem:
return rem_rest
else:
return [values[0]] + rem_rest
if values[0] == elem:
return _____________________
else:
return _____________________
is_pal('modem')
• what is its solution?
• what is the next smaller subproblem?
• what is the solution to that subproblem?
• how can we use the solution to the subproblem...?
What is our one step?
176
1 hundred + 7 tens + 6 ones
1*102 + 7*101 + 6*100
10110000
1*27 + 0*26 + 1*25 + 1*24 + 0*23 + 0*22 + 0*21 + 0*20
128 + 0 + 32 + 16 + 0 + 0 + 0 + 0
also 176!
10110000
• For each bit that is 1, add 2n, where n = the bit number
• example:
0 1 0 1 1 1 0 1
b7 b6 b5 b4 b3 b2 b1 b0
decimal value = 26 + 24 + 23 + 22 + 20
______________________
1 1
12537
+ 9272
21809
01110
+ 11100
base 2 base 10
______
______
• For each bit that is 1, add 2n, where n = the bit number
• example:
0 1 0 1 1 1 0 1
b7 b6 b5 b4 b3 b2 b1 b0
decimal value = 26 + 24 + 23 + 22 + 20
64 + 16 + 8 + 4 + 1 = 93
base 2 base 10
dec_to_bin() Function
• dec_to_bin(n)
• takes an integer n
• should return a string representation of n's binary
representation
>>> dec_to_bin(139)
'10001011'
>>> dec_to_bin(13)
'1101'
dec_to_bin(13)
dec_to_bin(6) + '1'
dec_to_bin(3) + '0'
dec_to_bin(1) + '1'
'1'
bin_to_dec('1101')
2 * bin_to_dec('110') + 1
2 * bin_to_dec('11') + 0
2 * bin_to_dec('1') + 1
1 1 1
01110
+ 11100
1101010
'terriers'
0111010001100101011100100111001001101001011001010111001001110011
inputs x
AND
y output
inputs output
x y x AND y
AND's
function: 0 0
0 1
1 0
1 1
OR Gate
OR outputs 1 if
any input is 1
inputs x
OR
OR
output
y
inputs output
x y x OR y
OR's
function: 0 0
0 1
1 0
1 1
NOT reverses
its input
input output
x NOT x
NOT's
function: 0
1
0 1
0 1
0
1 0
Boolean Notation
• Recall:
inputs output inputs output input output
x y x AND y x y x OR y x NOT x
0 *0 = 0 0 +0 = 0 0 1
0 *1 = 0 0 +1 = 1 1 0
1 *0 = 0 1 +0 = 1
1 *1 = 1 1 +1 = 1
• In boolean notation:
• x AND y is written as multiplication: xy
• x OR y is written as addition: x + y
• NOT x is written using a bar: x
• Example:
(x AND y) OR (x AND (NOT y)) ___________
Z
minterm
A
minterm
B
minterm
C
minterm
D
'terriers'
0111010001100101011100100111001001101001011001010111001001110011
PS 4: add_bitwise
1
• add_bitwise(b1, b2) 101010
b1 and b2 are strings representing binary #s + 001001
110011
• It should look something like this:
def add_bitwise(b1, b2):
if ... # base case #1
add_bitwise('100', '010')
b1: '100' b2: '010'
sum_rest = add_bitwise('10', '01')
add_bitwise('10', '01')
b1: '10' b2: '01'
sum_rest = add_bitwise('1', '0')
add_bitwise('1', '0')
b1: '1' b2: '0'
sum_rest = add_bitwise('', '')
add_bitwise('', '')
b1: '' b2: ''
base case: return ''
add_bitwise('100', '010')
b1: '100' b2: '010'
sum_rest = add_bitwise('10', '01')
add_bitwise('10', '01')
b1: '10' b2: '01'
sum_rest = add_bitwise('1', '0')
add_bitwise('1', '0')
b1: '1' b2: '0'
sum_rest = add_bitwise('', '')
add_bitwise('', '')
b1: '' b2: ''
base case: return ''
add_bitwise('1', '0')
b1: '1' b2: '0'
sum_rest = ''
if ...
return
add_bitwise('101', '011')
add_bitwise('101', '011')
b1: '101' b2: '011'
sum_rest = add_bitwise('10', '01')
add_bitwise('10', '01')
b1: '10' b2: '01'
sum_rest = add_bitwise('1', '0')
add_bitwise('1', '0')
b1: '1' b2: '0'
sum_rest = add_bitwise('', '')
add_bitwise('', '')
b1: '' b2: ''
base case: return ''
add_bitwise('101', '011')
b1: '101' b2: '011'
sum_rest = add_bitwise('10', '01')
add_bitwise('10', '01')
b1: '10' b2: '01'
sum_rest = add_bitwise('1', '0')
add_bitwise('1', '0')
b1: '1' b2: '0'
sum_rest = add_bitwise('', '')
add_bitwise('', '')
b1: '' b2: ''
base case: return ''
add_bitwise('101', '011')
b1: '101' b2: '011'
sum_rest = '11' # same as before
if ...
???
1
• We need to carry! 101
+ 011
110
1000
• We need to add 11 + 1 to get 100.
• how can we do this addition?
110011
ADDER 51
circuit
(3) read output
voltages
9
001001
00 00 000
00 01 001
00 10 010
00 11 011
01 00 001
01 01 010
01 10 011
01 11 bitwise 100
10 00 addition 010
10 01 function 011
10 10 100
10 11 101
11 00 011
11 01 100
11 10 101
11 11 110
A B
x
inputs y
z AND
w output
inputs output
x y z w AND(x,y,z,w)
AND's
function: 0 0 0 0 0
0 0 0 1 0 fifteen 0s
…12 more rows not shown… 0
1 1 1 0 0
1 1 1 1 1 one 1
OR outputs 1 if
any input is 1
x
inputs y
z OR
w output
inputs output
x y z w OR(x,y,z,w)
OR's
function: 0 0 0 0 0
0 0 0 1 1 one 0
…12 more rows not shown… 1
1 1 1 0 1
1 1 1 1 1 fifteen 1s
NOT Gate
NOT reverses
its input
"NOT bubble"
(optional)
input output
x NOT(x)
NOT's
function: 0 1
1 0
AND OR NOT
0 0
inputs
x y output
0 0
0 1
1 0
1 1
Claim
AND
OR
NOT
NOT AND
OR
NOT AND
x y
Constructive Proof!
NOT AND
OR
NOT AND
x y
NOT AND
OR
NOT AND
x y
• The top AND gate implements which row of the truth table?
minterm expansion =
xyz + xyz + xyz + xyz
minterm minterm minterm minterm
A B C D
• This truth table and circuit are for the odd parity function.
• outputs 1 when the number of 1 inputs is odd
A. yz + xz + xy
B. xyz + xyz + xyz + xyz
C. xyz + xyz + xyz + xyz
D. xyz + xyz + xyz + xyz
E. none of the above
for example:
• greater_than_4(1, 1, 0) 1 (True)
Why?
• greater_than_4(0, 1, 1) 0 (False)
because 0112 = 310, and 3 is not > 4
+ +
Z
minterm
A
minterm
B
minterm
minterm
CC
It tests whether
x == y.
Here's an alternative
version that adds
"rails" for Not X
and Not Y.
In some cases
(but not this one!),
doing so can reduce
the number of
NOT gates.
D
• Complete the rest of
the truth table.
• What is its minterm expansion as a formula/expression?
input output
x y z
A
0 0 0 0
0 0 1 0
0 1 0 0 B
0 1 1 1
1 0 0 0
1 0 1 1 C
1 1 0 1
1 1 1 1
D
CPU RAM
central processing unit random access memory
CPU RAM
central processing unit random access memory
0 0000 0001 0000 0001
1 1000 0010 0001 0001
2 0110 0010 0010 0001
3 0000 0010 0000 0010
4 0000 0000 0000 0000
5
6
Assembly Language
processing program + data
CPU RAM
central processing unit random access memory
0000 0001 0000 0001 0 read r1
1000 0010 0001 0001 1 mul r2 r1 r1
0110 0010 0010 0001 2 add r2 r2 r1
0000 0010 0000 0010 3 write r2
0000 0000 0000 0000 4 halt
5
6
CPU RAM
central processing unit random access memory
0 read r1
r1
1 mul r2 r1 r1
general‐purpose register r1
2 add r2 r2 r1
3 write r2
r2
4 halt
general‐purpose register r2
5
... 6
...
15 general-purpose registers (r1-r15) 256 memory locations
Screen
Executing a Program in Assembly
CPU RAM
central processing unit random access memory
0 read r1
r1
general‐purpose register r1 1 mul r2 r1 r1
r2 2 add r2 r2 r1
general‐purpose register r2
3 write r2
4 halt
CPU RAM
central processing unit random access memory
0 read r1
r1 6
general‐purpose register r1 1 mul r2 r1 r1
r2 2 add r2 r2 r1
general‐purpose register r2
3 write r2
4 halt
Screen 6 (input)
Executing a Program in Assembly
CPU RAM
central processing unit random access memory
0 read r1
r1 6
general‐purpose register r1 1 mul r2 r1 r1
r2 36 2 add r2 r2 r1
general‐purpose register r2
3 write r2
equivalent to:
4 halt
r2 = r1 * r1
6 * 6
36
CPU RAM
central processing unit random access memory
0 read r1
r1 6
general‐purpose register r1 1 mul r2 r1 r1
r2 42 2 add r2 r2 r1
general‐purpose register r2
3 write r2
equivalent to:
4 halt
r2 = r2 + r1
36 + 6
42
Screen 6 (input)
Executing a Program in Assembly
42 (output)
CPU RAM
central processing unit random access memory
0 read r1
r1 6
general‐purpose register r1 1 mul r2 r1 r1
r2 42 2 add r2 r2 r1
general‐purpose register r2
3 write r2
4 halt
add rX rY rZ rX = rY + rZ add r1 r1 r3
sub rX rY rZ rX = rY - rZ sub r4 r3 r2
mul rX rY rZ rX = rY * rZ mul r3 r1 r2
div rX rY rZ rX = rY // rZ div r2 r5 r6
mod rX rY rZ rX = rY % rZ mod r2 r1 r3
setn rX n rX = n setn r1 7
addn rX n rX = rX + n addn r1 -1
Notation:
• rX, rY, rZ is any register name (r1-r15)
• n is any integer from -128 to 127
Screen 7 (input)
Second Example
4 (output)
CPU RAM
central processing unit random access memory
r1 7 0 read r1
1 setn r2 2
r2 2
2 div r3 r1 r2
r3 4 3 addn r3 1
4 write r3
5 halt
CPU RAM
central processing unit random access memory
r1 7 0 read r1
1 setn r2 2
r2 2
2 div r3 r1 r2
r3 4 3 addn r3 1
4 write r3
7 / 2
rounded 5 halt
Screen 8 (input)
Divide by Two and Round
Fill in the details for this execution of the program!
CPU RAM
central processing unit random access memory
r1 0 read r1
1 setn r2 2
r2
2 div r3 r1 r2
r3 3 addn r3 1
4 write r3
5 halt
CPU RAM
central processing unit random access memory
0 read r1
r1 8
1 setn r2 2
r2 2 2 div r3 r1 r2
3 mod r4 r1 r2
r3 4
4 jeqz r4 6
r4 0 5 addn r3 1
equivalent to: 6 write r3
if r4 == 0:
jump to line 6 7 halt
Screen 7 (input)
Divide by Two and Round (Fixed!)
4 (output)
CPU RAM
central processing unit random access memory
0 read r1
r1 7
1 setn r2 2
r2 2 2 div r3 r1 r2
3 mod r4 r1 r2
r3 4
4 jeqz r4 6
r4 1 5 addn r3 1
6 write r3
7 halt
x y cin cout s
• Recall our bitwise algorithm: 0 0 0 0 0
0 1 1
0 0 1 0 1
101101
0 1 0 0 1
+ 001110 0 1 1 1 0
111011 1 0 0 0 1
1 0 1 1 0
• A full adder adds only one column. 1 1 0 1 0
1 1 1 1 1
• It takes 3 bits of input:
• x and y – one bit from each number being added
• cin – the carry bit into the current column
inputs outputs
3 input bits Full Adder
x y cin
x y cin cout s
0 0 0 0 0 subcircuit s output bit
0 0 1 0 1 for s
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1 2 output bits
1 0 1 1 0
subcircuit
1 1 0 1 0 for cout
cout output bit
1 1 1 1 1
"Rails" of each
bit and its inverse
FA
cout s
x y cin
FA
cout s
x y cin x y cin x1 x0
FA FA + y1 y0
cout s cout s s2 s1 s0
s2 s1 s0
x y cin x y cin x1 x0
FA FA + y1 y0
cout s cout s s2 s1 s0
s2 s1 s0
x y cin x y cin 10
FA FA + 11
cout s cout s
s2 s1 s0
0 1 1 1
8 input bits
+ 1 1 0 1
1 0 1 0 0 5 output bits
0 0 0 0 2 partial products
1 1 0 1
1 1 0 1 0 final answer
CPU RAM
central processing unit random access memory
Early Computers
The Mark I: Howard Aiken, Grace Hopper, et al.; Harvard, the 1940s/50s
http://www‐03.ibm.com/ibm/history/exhibits/markI/markI_reference.html
http://www‐03.ibm.com/ibm/history/exhibits/markI/markI_reference.html
an external
program tape
for the Mark I
CPU RAM
central processing unit random access memory
0 read r1
r1
1 mul r2 r1 r1
general‐purpose register r1
2 add r2 r2 r1
3 write r2
r2
4 halt
general‐purpose register r2
5
... 6
...
15 general-purpose registers (r1-r15) 256 memory locations
CPU RAM
central processing unit random access memory
0 read r1
r1
1 setn r2 9
r2 2 sub r3 r1 r2
r3 3 div r3 r3 r2
4 addn r3 -1
5 write r3
6 halt
Notation:
• rX is any register name (r1-r15)
• L is the line number of an instruction
Screen
‐6 (input)
What Does This Program Output?
CPU RAM
central processing unit random access memory
0 read r1
r1
1 jgtz r1 7
r2 2 setn r2 -1
3 mul r1 r1 r2
4 nop
5 nop
6 nop
• What Python / mathematical 7 write r1
function is this? 8 halt
CPU RAM
central processing unit random access memory
0 read r1
r1
1 jgtz r1 7
r2 2 setn r2 -1
3 mul r1 r1 r2
4 nop
5 nop
6 nop
7 write r1
8 halt
Extra Practice:
What Does This Compute as a Function of x?
RAM
random access memory
x
0 read r1
A. x3 + x2 – 4
B. x3 + 3x2 – 4 1 setn r2 3
C. 4x2 – 4 2 mul r2 r1 r1
D. 2x2 – 4 3 mul r1 r1 r1
E. none of these
4 add r1 r1 r2
5 addn r1 -4
How could you rearrange/ 6 write r1
modify these instructions
to compute x2 + 3x – 4? 7 halt
x
0 read r1
A. x3 + x2 – 4
B. x3 + 3x2 – 4 1 setn r2 3
C. 4x2 – 4 2 mul r2 r1 r1
D. 2x2 –4 3 mul r1 r1 r1
E. none of these
4 add r1 r1 r2
5 addn r1 -4
6 write r1
7 halt
x
r1 0 read r1
1 setn r2 3
r2
2 mul r2 r2 r1
3 mul r1 r1 r1
4 add r1 r1 r2
5 addn r1 -4
How could you rearrange/ 6 write r1
modify these instructions
to compute x2 + 3x – 4? 7 halt
Jumps in Hmmm
instruction what it does example
jeqz rX L jumps to line L if rX == 0 jeqz r1 12
jgtz rX L jumps to line L if rX > 0 jgtz r2 4
jltz rX L jumps to line L if rX < 0 jltz r3 15
jnez rX L jumps to line L if rX != 0 jnez r1 7
Notation:
• rX is any register name (r1-r15)
• L is the line number of an instruction
Screen
7 (1st input)
Checking for Invalid Inputs 3 (2nd input)
1 read r2
r1 7 2 sub r3 r2 r1
3 jltz r3 0
r2 3
4 write r1
r3 -4 5 jeqz r3 9
6 addn r1 1
• Lines 0-3 are known as a loop. 7 sub r3 r2 r1
8 jump 4
• The program loops back and repeats
9 halt
statements that have already been
executed.
Screen
For the Inputs At Right, 20 (1st input)
0 read r1
r1 1 read r2
2 sub r3 r1 r2
r2
3 nop
r3 4 jgtz r3 7
5 write r1
6 jumpn 8
7 write r2
8 halt
0 read r1
r1 1 read r2
2 sub r3 r1 r2
r2
3 nop
r3 4 jgtz r3 7
5 write r1
6 jumpn 8
7 write r2
• What if we swap the two inputs?
8 halt
• What Python function is this?
Screen
7 (1st input)
Follow-up Questions (cont.) 20 (2nd input)
0 read r1
r1 1 read r2
2 sub r3 r1 r2
r2
3 nop
r3 4 jgtz r3 7
5 write r1
6 jumpn 8
7 write r2
8 halt
• How could you change only line 3 so that, if the two inputs
are equal, the program will ask for new inputs?
0 read r1
r1 7 1 read r2
2 sub r3 r1 r2
r2 7
3 jeqz r3 0
r3 0 4 jgtz r3 7
5 write r1
• Lines 0-3 form a loop.
6 jumpn 8
• When the inputs are equal, 7 write r2
the program loops back and
8 halt
repeats those statements.
Screen
For the Inputs At Right, 2 (1st input)
note:
copy r3 r1 0 read r1
is equivalent to: 1 read r2
r3 = r1
2 copy r3 r1
Use a table for the registers! 3 sub r4 r2 r1
r1 r2 r3 r4 4 jeqz r4 12
5 nop
6 nop
7 nop
8 nop
9 addn r1 1
in general? 11 jumpn 3
12 write r3
13 halt
if necessary 8 nop
9 addn r1 1
• you may need to change
10 add r3 r3 r1
another register, too
11 jumpn 3
12 write r3
13 halt
0 read r1
1 call r14 4
r1 7
2 write r13
3 halt
r13
4 copy r13 r1
return address register
5 addn r1 -1
r14 2
6 mul r13 r13 r1
the return address – 7
the line # of the instruction jumpr r14
after the call
continued on the next slide
0 read r1
1 call r14 4
r1 6
2 write r13
3 halt
r13 42
4 copy r13 r1
return address register
5 addn r1 -1
r14 2
6 mul r13 r13 r1
the return address – 7
the line we now jump jumpr r14
back to
0 read r1 0 read r1
1 call r14 4 1 jump 4
2 write r13 2 write r13
3 halt 3 halt
4 copy r13 r1 4 copy r13 r1
5 addn r1 -1 5 addn r1 -1
6 mul r13 r13 r1 6 mul r13 r13 r1
7 jumpr r14 7 jump 2
0 read r1 0 read r1
1 call r14 7 1 jump 7
2 write r13 2 write r13
3 read r1 3 read r1
4 call r14 7 4 jump 7
5 write r13 5 write r13
6 halt 6 halt
7 copy r13 r1 7 copy r13 r1
8 addn r1 -1 8 addn r1 -1
9 mul r13 r13 r1 9 mul r13 r13 r1
10 jumpr r14 10 jump ???
• For example: r1 r2
5 5
4 20
3 60
2 120
1 120
0 done!
Screen
5 (input)
Factorial Using a Loop
CPU RAM
central processing unit random access memory
r1 r2 0 read r1
1 setn r2 1
2 jeqz r1 8
3 mul r2 r2 r1
4 addn r1 -1
5 jumpn 2
6 nop
7 nop
8 write r2
9 halt
0 read r1
1 call r14 4
r1
2 write r13
3 halt
r13
4 copy r13 r1
return address register
5 addn r1 -1
r14
6 mul r13 r13 r1
7 jumpr r14
0 read r1 0 read r1
1 call r14 4 1 jumpn 4
2 write r13 2 write r13
3 halt 3 halt
4 copy r13 r1 4 copy r13 r1
5 addn r1 -1 5 addn r1 -1
6 mul r13 r13 r1 6 mul r13 r13 r1
7 jumpr r14 7 jumpn 2
0 read r1 0 read r1
1 call r14 7 1 jumpn 7
2 write r13 2 write r13
3 read r1 3 read r1
4 call r14 7 4 jumpn 7
5 write r13 5 write r13
6 halt 6 halt
7 copy r13 r1 7 copy r13 r1
8 addn r1 -1 8 addn r1 -1
9 mul r13 r13 r1 9 mul r13 r13 r1
10 jumpr r14 10 jumpn ???
0 read r1
def foo(x):
1 call r14 4
y = x*(x-1)
return y 2 write r13
3 halt
x = int(input()) 4 copy r13 r1
y = foo(x)
5 addn r1 -1
y = y + x
print(y) What if we
6 add
mul this
r13 line?
r13 r1
7 jumpr r14
We want to add the user's input x
to the function's return value y
before printing y.
0 read r1
def foo(x):
1 call r14 4
y = x*(x-1)
return y 1.5 add r13 r13 r1
2 write r13 doesn't
x = int(input()) 3 work!
halt
y = foo(x)
4 copy r13 r1
y = y + x
5 the user's
print(y) addn r1 -1
input gets
6 mul r13 r13 r1 changed
7 jumpr r14
Screen
5 (input)
Tracing Our Fixed Program
CPU RAM
0 read r1
r1 1 setn r15 100
2 storer r1 r15
return value (the "result")
r13 3 call r14 8
4 loadr r1 r15
return address (line #)
5 add r13 r13 r1
r14
6 write r13
the stack pointer 7 halt
r15 8 copy r13 r1
9 addn r1 -1
10 mul r13 r13 r1
11 jumpr r14
...
100 the
101 stack
...
Notation:
rX, rY, rZ is any register (r1-r15) n is any integer in [-128, 127]
Notation:
• rX is any register name (r1-r15)
• L is the line number of an instruction
CPU RAM
central processing unit random access memory
r1 r2 0 read r1
5 1 1 setn r2 1
5 2 jeqz r1 8
4 20
3 60 3 mul r2 r2 r1
2 120 4 addn r1 -1
1 120
0 5 jumpn 2
6 nop
7 nop
8 write r2
9 halt
Screen
For the Input At Right, 8 (input)
r1 r2 r3 r4 r5 0 read r1
1 jeqz r1 11
2 jltz r1 11
3 setn r2 0
4 setn r3 1
5 setn r4 2
6 sub r5 r1 r3
7 jeqz r5 12
8 div r1 r1 r4
• Which lines make up the loop? 9 addn r2 1
10 jumpn 6
11 setn r2 -1
• When would the output be -1? 12 write r2
13 halt
0 read r1 input
3 halt
4 copy r13 r1
5 addn r1 -1
the function
6 mul r13 r13 r1
7 jumpr r14 "return"
Screen
For the Inputs At Right, 8 (1st input)
(2nd input)
2
What Is the Output of this Program? 5 (3rd input)
0 read r1
def foo(x):
1 call r14 4
y = x*(x-1)
return y 2 write r13
3 halt
x = int(input()) 4 copy r13 r1
y = foo(x)
5 addn r1 -1
y = y + x
print(y) What if we
6 add
mul this
r13 line?
r13 r1
7 jumpr r14
We want to add the user's input x
to the function's return value y
before printing y.
0 read r1
def foo(x):
1 call r14 4
y = x*(x-1)
return y 1.5 add r13 r13 r1
2 write r13 doesn't
x = int(input()) 3 work!
halt
y = foo(x)
4 copy r13 r1
y = y + x
5 the user's
print(y) addn r1 -1
input gets
6 mul r13 r13 r1 changed
7 jumpr r14
for Loops
• A for statement is one way to create a loop in Python.
• allows us to repeat one or more statements.
• Example:
for i in [1, 2, 3]:
print('Warning')
the body of the loop
print(i)
will output:
Warning
1
Warning
2
Warning
3
does the
sequence have
more values? no
yes
execute statement
after the loop
does
[1, 2, 3] have
more values? no
more? i output/action
yes
print('Warning')
print(i)
print('That's all.')
• Example:
for i in range(3): # [0, 1, 2]
print('I'm feeling loopy!')
outputs:
I'm feeling loopy!
I'm feeling loopy!
I'm feeling loopy!
• Example:
for i in range(5):
print('I'm feeling loopy!')
outputs:
Python Shortcuts
• Consider this code:
age = 13
age = age + 1
13 + 1
14
• Instead of writing
age = age + 1
we can just write
age += 1
x result
def sum(vals):
result = 0
for x in vals:
result += x
return result
i
def sum(vals):
result = 0
for i in range(len(vals)):
result += vals[i]
return result
i vals[i] result
does the
sequence have
more values? no
yes
execute statement
after the loop
for i in __________________:
print('Warning!')
A. range(20)
B. [1] * 20
C. 'abcdefghijklmnopqrst'
D. either A or B would work, but not C
E. A, B or C would work
def sum(vals):
result = 0
for x in vals:
result += x
return result
i
def sum(vals):
result = 0
for i in range(len(vals)):
result += vals[i]
return result
i
def sum(vals): def sum(vals):
result = 0 result = 0
for x in vals: for i in range(len(vals)):
result += x result += vals[i]
return result return result
• Example:
for i in range(7):
print(i * 5)
0
5
10
15
20
25
30
• Examples:
for i in range(7):
print(i * 5, end=' ')
0 5 10 15 20 25 30
for i in range(7):
print(i * 5, end=',')
_____________________________________
• Python:
def print_multiples(n, bound):
mult = n
while mult < bound:
print(mult, end=" ")
mult = mult + n
print()
while Loops
False
false
Steps: loop test
condition
• Examples:
>>> remove_vowels('recurse')
'rcrs'
>>> remove_vowels('vowels')
'vwls'
False
false
Steps: loop test
condition
Extreme Looping!
• What does this code do?
print('It keeps')
while True:
print('going and')
print('Phew! Done!')
• random.choice(vals)
• takes a sequence vals
• randomly chooses one value from vals and returns it
while True:
print('Help!')
if random.choice(range(10000)) == 111:
break
print('Let me out!') A break statement causes
a loop to end early.
print('At last!')
• jumps to the line that
comes after the loop
count = 0
while True:
count += 1
print('Help!')
if random.choice(range(10000)) == 111:
break
print('Let me out!')
User Input
• Getting a string value from the user:
variable = input(prompt) where prompt is a string
• Examples:
name = input('What is your name? ')
count = int(input('possible points: '))
scores = eval(input('list of scores: '))
while True:
val = int(input('Enter a positive number: '))
if val > 0:
break
else:
print(val, 'is not positive. Try again!')
result = math.sqrt(val)
print('result =', result)
for while
definite indefinite
loop loop
i
def sum(vals): def sum(vals):
result = 0 result = 0
for x in vals: for i in range(len(vals)):
result += x result += vals[i]
return result return result
vals
L == [ 45, 80, 10, 30, 27, 50, 5, 15 ]
vals
L == [ 45, 80, 10, 30, 27, 50, 5, 15 ]
m is the
"min so far"
def minval(vals):
m = __________
for x in vals:
if x < m:
m = x
return m
0 1 2 3 4 5 6 7
L = [ 45, 80, 10, 30, 27, 50, 5, 15 ]
m m m
= = =
45 10 5 6
should
def minval_posn(vals): be
returned
# initialize variable(s)
for ______________________:
if _________:
# update var(s)
return ________
def is_prime(n):
max_div = int(math.sqrt(n)) # max possible divisor
def is_prime(n):
max_div = int(math.sqrt(n)) # max possible divisor
• examples:
• any_below([50, 18, 25, 30], 20) should return True
• any_below([50, 18, 25, 30], 10) should return False
return False
2 (1,1)
Estimating π
by dart throwing!
area π
=
area 4
1
4* area
π=
area
"hits"
4 * darts in
π~
darts in
(-1,-1) "throws"
pi_two(n) n == number of
darts to throw
Thinking in Loops
for while
definite indefinite
iteration iteration
Repeating a Repetition!
for i in range(3): # 0, 1, 2
for j in range(4): # 0, 1, 2, 3
print(i, j)
0 0
0 1
0 2
0 3
1 0
1 1
1 2
1 3
2 0
2 1
2 2
2 3
Nested loops
and
2D structure
for r in range(h):
for c in range(w):
# process the pixel at (r, c)
for y in range(84):
for m in range(12):
for d in range(f(m,y)):
for h in range(24):
for mn in range(60):
for s in range(60):
tick()
print('(8) Quit')
print()
...
• You may not use the built-in sum, min, or max functions.
• use your own loops instead!
To be realistic, however (for the SEC), you may only sell after you buy.
return mindiff
Printing Patterns
col
0 1 2 3
0 # # # #
# # # #
row
2
# # # #
col
0 1 2 3 4 5
0 1 2 3 4 5
row
0 1 2 3 4 5
col
0 0 0 0 0 0
1 1 1 1 1 1
row
2 2 2 2 2 2
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
http://www.asciimation.co.nz/
• Rather:
• the value is somewhere else in memory
• the variable stores the memory address of the value.
• Example: x = 7
Memory
4000
x 4001 4001 7
4002
4003
...
References
Memory
4000
x 4001 4001 7
4002
4003
...
x 7
prices
25 10 30 45
x 7
x 7
4
25 10 30 45
25 10 50 30 45
prices
25 50 30 45
18 20 4
• The same thing holds for list elements that are immutable.
prices = [25, 10, 30, 45]
prices 25 10 30 45
Copying Variables
• The assignment
var2 = var1
copies the contents of var1 into var2:
x = 50 x 50
y = x
y 50
list1 7 8 9 6 10 7 9 5
list2
• Given the lines of code above, what will the lines below print?
list2[2] = 4
print(list1[2], list2[2])
Copying a List
• We can copy a list like this one using a full slice:
list1 = [7, 8, 9, 6, 10, 7, 9, 5]
list2 = list1[:]
list1 7 8 9 6 10 7 9 5
list2 7 8 9 6 10 7 9 5
def triple(vals):
for i in range(len(vals)):
vals[i] = vals[i] * 3
main main
a a
1 2 3 3 6 9
Recall: References
x = 7 Memory
4000
x 4001 4001 7
4002
4003
...
s 'hello'
s 'hello'
'goodbye'
prices
25 10 30 45
25 10 50 30 45
• The same thing holds for list elements that are immutable.
prices = [25, 10, 30, 45]
prices 25 10 30 45
list1 7 8 9 6 10 7 9 5
list2
The variables are like
two business cards that
both have the address
of the same office.
list1 7 8 9 6 10 7 9 5
list2 7 8 9 6 10 7 9 5
list1
list2
list3
list2
list1 7 8 4
list2
list2
list1 7 8 9
list2 4 5 6
a = [1, 2, 3]
mystery1(a)
print(a)
a = [1, 2, 3]
mystery2(a)
print(a)
a = 2
mystery3(a)
print(a)
i = 0
l1 = [1, 1, 1]
l2 = l1
foo(l2, i)
print(i, l1, l2)
foo
i
vals
global global global
l2 l2 l2
l1 l1 l1
i i i
i = 0
l1 = [1, 1, 1]
l2 = l1
foo(l2, i)
print(i, l1, l2) # output: 0 [1, 2, 1] [1, 2, 1]
foo
1
i 0
vals
global global 2 global
l2 1 1 1 l2 1 1 1 l2 1 2 1
l1 l1 l1
i 0 i 0 i 0
2-D Lists
• Recall that a list can include sublists
mylist = [17, 2, [2, 5], [1, 3, 7]]
0 1 2 3 4 5 6 7 column
0 15 8 3 16 12 7 9 5 indices
1 6 11 9 4 1 5 8 13
2 17 3 5 18 10 6 7 21
3 8 14 13 6 13 12 8 4
row 4 1 9 5 16 20 2 3 9
indices
examples:
>>> print(table[2][1])
3 column index
row index
>>> table[-1][-2] = 0
for r in range(len(table)):
for c in range(len(table[0])):
# process table[r][c]
2-D Lists
• Recall that a list can include sublists
mylist = [17, 2, [2, 5], [1, 3, 7]]
• what is len(mylist)?
• what is len(table)?
• what does table[0] represent?
table[1]?
table[-1]?
• what is len(table[0])?
• what is table[3][1]?
A. count = 0
for r in range(len(table)):
for c in range(len(table[0])):
if table[r][c] % 2 == 0:
count += 1
B. count = 0
for r in len(table):
for c in len(table[0]):
if c % 2 == 0:
count += 1
C. count = 0
for r in range(len(table[0])):
for c in range(len(table)):
if table[r][c] % 2 == 0:
count += 1
D. either A or B E. either A or C
0 1 2 3 4 5 6 7 column
0 15 8 3 16 12 7 9 5 indices
1 6 11 9 4 1 5 8 13
2 17 3 5 18 10 6 7 21
3 8 14 13 6 13 12 8 4
row 4 1 9 5 16 20 2 3 9
indices
15 8 3 16 12 7 9 5
6 11 9 4 1 5 8 13
17 3 5 18 10 6 7 21
8 14 13 6 13 12 8 4
1 9 5 16 20 2 3 9
table
list1 7 8 9 6 10 7 9 5
list2
list1 7 8 9 6 10 7 9 5
list2 7 8 9 6 10 7 9 5
x 7
global global global
vals 7 7 vals 7 7 vals 7 7
x 7 x 7 x
grid1
grid2 1 2 3 4 5 6 7 8
A Shallow Copy
grid1 = [[1, 2], [3, 4], [5, 6], [7, 8]]
grid3 = grid1[:]
grid1
1 2 3 4 5 6 7 8
grid3
grid1
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
grid3
PS 7: Image Processing
• Other examples:
• pure red: [255, 0, 0]
• pure green: [0, 255, 0]
• pure blue: [0, 0, 255]
• white: [255, 255, 255]
• black: [0, 0, 0]
What Is An Object?
• An object is a construct that groups together:
• one or more data values (the object's attributes)
• one or more functions that operate on those data values
(known as the object's methods)
contents 'h' 'e' 'l' 'l' 'o' contents 'b' 'y' 'e'
length 5 length 3
Calling a Method
• An object's methods are inside the object,
so we use dot notation to call them.
string object for 'Perry'
• Example:
the dot contents 'P' 'e' 'r' 'r' 'y'
name = 'Perry'
length 5
allcaps = name.upper()
upper() replace()
the object's the method lower() split()
variable name find() ...
count()
Splitting a String
• The split() method breaks a string into a list of substrings.
>>> name = ' Martin Luther King '
>>> name.split()
['Martin', 'Luther', 'King']
>>> components = name.split()
>>> components[0]
'Martin'
______________________________
Text Files
• A text file can be thought of as one long string.
Don't forget!
• Example:
f = open('reminder.txt', 'r')
where:
• 'reminder.txt' is the name of the file we want to read
• 'r' indicates that we want to read from the file
_____________
>>> f = open('reminder.txt', 'r') # start over at top
>>> f.read()
"Don't forget!\n\nTest your code fully!\n"
>>> chant.lower()
Closing a File
• When you're done with a file, close your connection to it:
file.close() # file is the file handle
• another example of a method inside an object!
file.close()
Mike Mercury,BU,mile,4:50:00
Steve Slug,BC,mile,7:30:00
Len Lightning,BU,half-mile,2:15:00
Tom Turtle,UMass,half-mile,4:00:00
fields = line.split(',')
if fields[1] == target_school:
print(fields[0], fields[2], fields[3])
else:
print(target_school, 'not found')
file.close()
count = 0
for line in file:
line = line[:-1] # chop off newline at end
fields = line.split(',')
if fields[1] == target_school:
print(fields[0], fields[2], fields[3])
count += 1
if count == 0:
print(target_school, 'not found')
file.close()
width
• it's used to create new objects
• it specifies the attributes height
r1 x 0 r2 x 0
y 0 y 0
• Modify them as you would any other variable: Fill in the updated
field values.
>>> r1.x = 25
>>> r1.y = 10 r1 x
>>> r1.width *= 2
y
width
height 50
a Rectangle object
x 200
coordinates of
y 150 its upper-left
corner
width 50
height 30
class Rectangle:
""" the Rectangle constructor """
def __init__(self, init_width, init_height):
self.x = 0
self.y = 0
self.width = init_width
self.height = init_height
Calling a Method
class Rectangle:
...
def grow(self, dwidth, dheight):
self.width += dwidth
self.height += dheight
before grow
>>> r1 = Rectangle(100, 50)
>>> r1.width
125
after grow
>>> r1.height
___________
def area(self):
return self.width * self.height
def area(self):
return self.width * self.height
r1 = Rectangle(100, 50)
r1.grow(50, 10)
print('r1:', r1.width, 'x', r1.height)
grow x 0
self y 0
r1 = Rectangle(100, 50)
r1.grow(50, 10)
print('r1:', r1.width, 'x', r1.height)
output: _________________
x 0
y 0
width
height
global
r1
Another Analogy
• A class is like a cookie cutter.
• specifies the "shape" that all objects
of that type should have
r1 x 0 r2 x 0
y 0 y 0
def area(self):
return self.width * self.height
r1 = Rectangle(100, 50)
r2 = Rectangle(20, 80)
B.
def perimeter():
return 2*self.width + 2*self.height
C.
def perimeter(self):
return 2*self.width + 2*self.height
r = Rectangle(35, 20)
perim = ________________________
def scale(______________________):
r1.scale(5)
r2.scale(3)
print(r1.width, r1.height, r2.width, r2.height)
__init__ x 0
self
y 0
init_
width 100
width 100
init_
height
50
height 50
global
r1
r2
r1.scale(5)
r2.scale(3)
print(r1.width, r1.height, r2.width, r2.height)
x 0
y 0
width 100
height 50
global
r1
r2
r1.scale(5)
r2.scale(3)
print(r1.width, r1.height, r2.width, r2.height)
__init__ x 0
self
y 0
init_
width 20
width 100
init_ x 0
height
80
height 50
global y 0
r1 width 20
r2 height 80
r1.scale(5)
r2.scale(3)
print(r1.width, r1.height, r2.width, r2.height)
x 0
y 0
width 100
x 0
height 50
global y 0
r1 width 20
r2 height 80
r1.scale(5)
r2.scale(3)
print(r1.width, r1.height, r2.width, r2.height)
x 0
scale y 0
self
width 500
factor 5 x 0
height 250
global y 0
r1 width 20
r2 height 80
r1.scale(5)
r2.scale(3)
print(r1.width, r1.height, r2.width, r2.height)
x 0
scale y 0
self
width 500
factor 3 x 0
height 250
global y 0
r1 width 60
r2 height 240
x 0
y 0
width 500
x 0
height 250
global y 0
r1 width 60
r2 height 240
scale
self
factor 3 x 0
global y 0
r1 width 60
r2 height 240
class Rectangle:
def __init__(self, init_width, init_height):
self.x = 0
self.y = 0
self.width = init_width
self.height = init_height
x 0
y 0
width 40
global x 0
height 75
r1 y 0
r2 width 40
r3 height 75
_____________
class Rectangle:
def __init__(self, init_width, init_height):
self.x = 0
self.y = 0
self.width = init_width
self.height = init_height
scale x 0
self
y 0
factor
width 40
global x 0
height 75
r1 y 0
r2 width 40
r3 height 75
x 0
y 0
width 40
global x 0
height 75
r1 y 0
r2 width 40
r3 height 75
print('r2:', r2)
print('area =', r2.area())
PS 8: Date Class
class Date:
def __init__(self, init_month, init_day, init_year): month 11
""" constructor that initializes the
three attributes day 11
"""
# you will write this! year 1918
def __repr__(self):
"""This method returns a string representation for the
object of type Date that calls it (named self).
"""
s = "%02d/%02d/%04d" % (self.month, self.day, self.year)
return s
def is_leap_year(self):
""" Returns True if the calling object is
in a leap year. Otherwise, returns False.
"""
if self.year % 400 == 0:
return True
elif self.year % 100 == 0:
return False
elif self.year % 4 == 0:
return True
return False
days_in_month = [0,31,28,31,30,31,30,31,31,30,31,30,31]
if self.is_leap_year() == True:
days_in_month[2] = 29
A. d1.is_before(d2) C. d3.is_before(d1)
fields = line.split(',')
if fields[1] == target_school:
print(fields[0], fields[2], fields[3])
file.close()
Mike Mercury,BU,mile,4:50:00
Steve Slug,BC,mile,7:30:00
Len Lightning,BU,half-mile,2:15:00
Tom Turtle,UMass,half-mile,4:00:00
• Now we'd like to count the number of results from each school,
and report all of the counts:
>>> school_counts('results.txt')
There are 3 schools in all.
BU has 2 result(s).
BC has 1 result(s).
UMass has 1 result(s).
What is a Dictionary?
• A dictionary is a set of key-value pairs.
>>> counts = {'BU': 2, 'UMass': 1, 'BC': 1}
general syntax:
{key1: value1, key2: value2, key3: value3...}
• We can use the key like an index to lookup the associated value!
>>> counts['BU']
2
>>> counts['BC']
1
key value
>>> counts['BC'] = 1
>>> counts # a set of key: value pairs
{'BU': 2, 'BC': 1}
>>> counts['BU'] # use the key to get the value
2
>>> counts['BC']
1
>>> counts['UMass'] = 1
>>> counts
{'BU': 2, 'UMass': 1, 'BC': 1} # order is not fixed
________________
• More generally:
for key in dictionary:
# code to process key-value pair goes here
count = 0
for x in d:
if x > 5:
count += 1
print(count)
words = text.split()
d = {}
for word in words:
if word not in d:
d[word] = 1
else:
d[word] += 1
return d
Shakespeare, Anyone?
>>> freqs = word_frequencies('romeo.txt')
>>> freqs['Romeo'] Act I of Romeo & Juliet.
1 See PS 8!
>>> d = create_dictionary('romeo.txt')
>>> generate_text(d, 50)
ROMEO: Out of mine own word: If you merry! BENVOLIO:
Come, go to. She hath here comes one of the year, Come
hither, nurse. ROMEO: Well, in spite, To be gone.
BENVOLIO: For men depart.[Exeunt all Christian souls!-
Were of wine. ROMEO: Bid a sea nourish'd with their
breaths with
>>> d2 = create_dictionary('mission.txt')
>>> generate_text(d2, 20)
We remain dedicated to benefit society. Boston
University is an ever-changing world. Boston University
comprises a strong foundation of diversity,
Markov Models
• Allow us to model any sequence of real-world data.
• human speech
• written text
• sensor data
• etc.
generate_text(word_dict, num_words)
>>> d = create_dictionary('edited_mission.txt')
A. 'a': ['comprehensive']
B. 'It': ['is']
C. 'knowledge.': ['new']
PS 9: Connect Four!
• Two players, each with one type of checker
Board Objects
• To facilitate testing, we'll allow for dimensions other than 6 x 7.
• example:
b = Board(5, 6) ' ' ' ' ' ' ' ' ' ' ' '
Board object ' ' ' ' ' ' 'X' ' ' ' '
b
height 5 ' ' ' ' 'O' 'X' 'O' ' '
width 6
' ' 'X' 'O' 'X' 'O' ' '
slots
'X' 'O' 'O' 'O' 'X' 'X'
Board object ' ' ' ' ' ' 'X' ' ' ' '
b
height 5 ' ' ' ' 'O' 'X' 'O' ' '
width 6
' ' 'X' 'O' 'X' 'O' ' '
slots
'X' 'O' 'O' 'O' 'X' 'X'
Board Constructor
class Board:
""" a data type for a Connect Four board with
arbitrary dimensions
"""
def __init__(self, height, width):
""" a constructor for Board objects """
self.height = height
self.width = width
self.slots = _______________________________
' ' ' ' ' ' ' ' ' ' ' '
Board object ' ' ' ' ' ' ' ' ' ' ' '
height 5 ' ' ' ' ' ' ' ' ' ' ' '
width 6
' ' ' ' ' ' ' ' ' ' ' '
slots
' ' ' ' ' ' ' ' ' ' ' '
Board object ' ' ' ' ' ' ' ' ' ' ' '
height 5
get height copies of
width 6
the reference to the list
slots created by [[' ']*width]
__repr__ Method
def __repr__(self):
""" returns a string representation of a Board """
s = '' # begin with an empty string
return s
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | |O| |O| | |
| |X|O|X|X|O| |
| |O|O|O|X|X|X|
---------------
0 1 2 3 4 5 6
self.slots[???][col] = checker
# no return needed!
row = 0
while self.slots[row][col] == ' ':
row += 1
self.slots[row][col] = checker
A. b.add_checker('X', 0) Board b
| | | | | | | |
B. b.add_checker('O', 6) | | | | | | | |
| | | | | | | |
C. b.add_checker('X', 2) | | |O| |O| | |
| |X|O|X|X|O| |
D. A and B | |O|O|O|X|X| |
---------------
E. A, B, and C 0 1 2 3 4 5 6
def __repr__(self):
... Player object
p
def opponent_checker(self): checker 'X'
... num_moves 0
while True:
col = int(input('Enter a column: '))
# if valid column index, return that integer
# else, print 'Try again!' and keep looping
def __repr__(self):
""" This method returns a string representation for the
object of type Date that calls it (named self).
"""
s = "%02d/%02d/%04d" % (self.month, self.day, self.year)
return s
def is_leap_year(self):
""" Returns True if the calling object is
in a leap year. Otherwise, returns False.
"""
if self.year % 400 == 0:
return True
elif self.year % 100 == 0:
return False
elif self.year % 4 == 0:
return True
return False
• a day day 28
• a year year 2019
• a name (e.g., 'Thanksgiving') name 'Thanksgiving'
• an indicator of whether islegal True
it's a legal holiday
Inheritance in PS 9
• Player – the superclass
• includes fields and methods needed by all C4 players
• in particular, a next_move method
• use this class for human players
Inheritance in PS 9
• Player – the superclass
• includes fields and methods needed by all C4 players
• in particular, a next_move method
• use this class for human players
• Scoring columns:
–1: an already full column
0: if we choose this column, it will result in a loss
at some point during the player's lookahead
100: if we choose this column, it will result in a win
at some point during the player's lookahead
50: if we choose this column, it will result in
neither a win nor a loss during the player's lookahead
A Lookahead of 0
• A lookahead-0 player only assesses the current board
(0 moves!).
LA-0 scores for
'X'
-1 50 50 50 50 50 50 'O'
to
move
1 move is made!
A lookahead-1 player
to will "see" an
move
impending victory.
next_move
will return 4!
A Lookahead of 1
• A lookahead-1 player assesses the outcome of only
the considered move.
1 move is made!
to
move
A lookahead-2 player
to will "see" a way to win
move
or
a way to block the
opponent's win.
Example 2: LA-0
• A lookahead-0 player only assesses the current board
(0 moves!).
to
move
to
move
Example 2: LA-2
• A lookahead-2 player looks 2 moves ahead.
• what if I make this move, and then my opponent makes
its best move?
• note: we assume the opponent looks ahead 2 – 1 = 1 move
to
move
to
move
Example 2: LA-0
• A lookahead-0 player only assesses the current board
(0 moves!).
to
move
to
move
A. 50 50 100 50 50 50 -1 no change?
B. 0 0 100 0 0 0 -1
C. 50 50 100 50 0 50 -1
to
move
to
move
LA-4!
• A lookahead-4 player looks 4 moves ahead.
• assumes the opponent looks ahead 4 – 1 = 3 moves
to
move
'X'
???
return scores
col 1
opp_scores = [0,0,0,0,0,0,0]
max(opp_scores) = 0
opp_scores = [0,0,0,0,0,0,0]
scores[2] = 100
max(opp_scores) = 0
scores[0] = 100
A loss for my opponent opp_scores = [50,50,50,50,50,100,50]
is a win for me! max(opp_scores) = 100
scores[1] = 0
A win for my opponent is a loss for me!
col 4
col 5
opp_scores =
[50,50,50,50,50,100,50]
max(opp_scores) = 100
opp_scores = [0,0,0,0,0,0,0] scores[6] = 0
max(opp_scores) = 0
scores[4] = 100
opp_scores = [50,50,50,50,50,50,50]
max(opp_scores) = 50
scores[5] = 50
A draw for my opponent is a draw for me!
col 0 col 6
scores[1] = 0 scores[5] = 50
scores[2] = 100 scores[3] = 100 scores[4] = 100
return scores
col 0 col 6
scores[1] = 0 scores[5] = 50
scores[2] = 100 scores[3] = 100 scores[4] = 100
What should
return [100, 0, 100, 100, 100, 50, 0] next_move
return?
0 1 2 3 4 5 6
return [100, 0, 100, 100, 100, 50, 0]
• possible moves: _______________
Recall: Inheritance in PS 9
• Player – a class for human Connect Four players
• includes fields and methods needed by all C4 players
• in particular, a next_move method
...
• It depends!
• if p is a Player object, call next_move from that class
• if p is a RandomPlayer, call that version of next_move
• if p is an AIPlayer, call that version of next_move
• Consists of:
• one or more states (the circles)
• exactly one of them is the start / initial state
• zero or more of them can be an accepting state
• a set of possible input characters (we're using {0, 1})
• transitions between states, based on the inputs
0
1 Make sure that each
state has:
q2 • exactly one outgoing
0 1
transition for 0
0
• exactly one outgoing
1
transition for 1
q0 q1
111 is
accepted!
q2
0 0 1
1
q0 q1
q1
0 0
1 1 1
0
q0 q2
0 0 1
q0 q1 q2 q3
1 0
start
1
• multiple of 3 = 0, 3, 6, 9, …
• number of 1s doesn't matter
• accepted strings include: 110101110, 11, 0000010
• rejected strings include: 101, 0000, 111011101111
• you may not need all four states!
1 1
0 0
0 s 1
s0 s1
0 0 1
1
s00 s01 s10 s11
0 1 0 1 0 1 0 1
Third-to-Last Bit Is a 1
Construct a FSM accepting strings in which
the third-to-last bit is a 1.
0 s 1
s0 s1
0 0 1
1
s00 s01 s10 s11
0 1 0 1 0 1 0 1
A. C.
B. D.
q2 q3
q0 q1
0 0
Limitations of FSMs
• Because they're finite, FSMs can only count finitely high!
WWII
Enigma machine ~ The
axis's encryption engine
Bletchley Park
1946
WWII
Enigma machine ~ The
axis's encryption engine
Bletchley Park
1946
• Quantum computation
http://www.cs.virginia.edu/~robins/The_Limits_of_Quantum_Computers.pdf
• Molecular computation
http://www.arstechnica.com/reviews/2q00/dna/dna-1.html
• Parallel computers
• Integrated circuits
• Electromechanical computation
• Water-based computation
• Tinkertoy computation
Algorithm Efficiency
• This semester, we've developed algorithms for many tasks.
return None
• Example:
lst 35 6 19 23 3 47 9 15
lst 3 6 9 15 19 23 35 47
Selection Sort
• Basic idea:
• consider the positions in the list from left to right
• for each position, find the element that belongs there and
swap it with the element that’s currently there
• Example:
0
0 1 2 3 4
15 6 2 12 4
0 1
1 2 3 4
2 6 15 12 44
0 1 2
2 3 4 0 1 2 3
3 4
2 4 15 12 66 2 4 6 12 15
E. none of these
Quicksort
• Another possible sorting algorithm is called quicksort.
• It uses recursion to "divide-and conquer":
• divide: rearrange the elements so that we end up with two
sublists that meet the following criterion:
• each element in the left list <= each element in the right list
example:
12 8 14 4 6 13 6 8 4 14 12 13
• Others include:
cn # exponential growth
n! # factorial growth
• Assume there are only 4 possible positions for each point's label:
upper left upper right
• Not very!
Classifying Problems
• "Easy" problems: can be solved using an algorithm with a
growth function that is a polynomial of the problem size, n.
• we can solve large problem instances in a
reasonable amount of time