Python Algorithms Overview
Python Algorithms Overview
Agenda
- language overview
- built-in types, operators and constructs
- functions, classes, and modules
- stdlib: I/O, testing, timing
Computer
Science Science
Not exhaustive!
- this is not a language course
- Python is a means to an end
(writing data structures & algorithms)
- you are responsible for mastering the
language!
Computer
Science Science
IDE recommendation
- We will not be using an official IDE
- Text editor (vim/emacs) + command
line interpreter will suffice
- If you want/need one, I recommend
PyCharm (from [Link])
Computer
Science Science
§Overview
Computer
Science Science
Python is …
interpreted,
dynamically-typed,
automatically memory-managed,
and supports procedural, object-oriented,
imperative and functional paradigms
Computer
Science Science
§Types, Operators
and Constructs
(that matter to us)
Computer
Science Science
Boolean operators
Comparison operators
Computer
Science Science
Numeric operators
Computer
Science Science
[Link]
Computer
Science Science
Compound types
>>> 'hello'
'hello'
>>> 'hello' + ' ' + 'world'
'hello world'
>>> 'lo wo' in ('hello' + ' ' + 'world')
True
>>> 'world' * 3
'worldworldworld'
>>> len('hello')
5
>>> 'hello world'[3:10]
'lo worl’
>>> 'hello'[2:4] = 'ww'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
Computer
Science Science
puzzle = """4.....8.5
.3.......
...7..... (newlines (‘\n'))
...
.2.....6.
(whitespace) ....8.4..
....1....
...6.3.7.
5..2.....
1.4......"""
Computer
Science Science
.3.......
...7.....
.2.....6.
....8.4..
....1....
...6.3.7.
5..2.....
1.4......"""
[ '4.....8.5',
'.3.......',
'...7.....',
'.2.....6.',
'....8.4..',
'....1....',
'...6.3.7.',
'5..2.....',
‘1.4......' ]
Computer
Science Science
Hewwo-uh-wabbit
Computer
Science Science
for r in puzzle_rows:
print(r, '->', [Link]('.'), 'blanks')
blank_counts = []
for r in puzzle_rows:
blank_counts.append([Link]('.'))
[6, 8, 8, 7, 7, 8, 6, 7, 7]
[6, 8, 8, 7, 7, 8, 6, 7, 7]
Computer
Science Science
rows = 'ABCDEFGHI'
cols = '123456789'
squares = []
for r in rows:
for c in cols:
[Link](r + c)
print(len(squares))
print(squares[0:len(squares):5])
81
[ 'A1', 'A6', 'B2', 'B7', 'C3', 'C8', 'D4', 'D9',
'E5', 'F1', 'F6', 'G2', 'G7', 'H3', 'H8', 'I4', 'I9']
Computer
Science Science
rows = 'ABCDEFGHI'
cols = '123456789'
print(len(squares))
print(squares[0:len(squares):5])
81
[ 'A1', 'A6', 'B2', 'B7', 'C3', 'C8', 'D4', 'D9',
'E5', 'F1', 'F6', 'G2', 'G7', 'H3', 'H8', 'I4', 'I9']
Computer
Science Science
identifying “units”
rows = 'ABCDEFGHI'
cols = '123456789'
rows = 'ABCDEFGHI'
cols = '123456789'
all_units = # ?
print(len(all_units))
print(all_units)
27
[['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
...
['I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9'],
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
...
['A9', 'B9', 'C9', 'D9', 'E9', 'F9', 'G9', 'H9', 'I9'],
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'],
...
['G7', 'G8', 'G9', 'H7', 'H8', 'H9', 'I7', 'I8', 'I9']]
Computer
Science Science
hints:
- result is the concatenation of multiple list
comprehension expressions
- each list comprehension must create
a list of lists (each unit is a list)
- try to do it in pieces first!
Computer
Science Science
Computer
Science Science
c2_units = # ?
Computer
Science Science
print(square_units[0])
('A1',
[['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A1', 'B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']])
Computer
Science Science
to_find = 'C2'
for entry in square_units:
if entry[0] == to_find:
units = entry[1]
break
else: # enter when loop exhausts all values (i.e., no break)
units = None # special value that represents ... nothing
print(units)
Operation Result
Dictionary operations
Computer
Science Science
try:
dd_ego = alter_egos['Dr. Doom']
except:
print("Dr. Doom's alter ego not known")
else:
print('Dr. Doom =', dd_ego)
finally:
print('Thanks for playing!')
print(alter_egos.get('Superman', 'unknown'))
print(alter_egos.get('Dr. Doom', 'unknown'))
Clark Kent
unknown
Computer
Science Science
print(alter_egos.get('Superman'))
print(alter_egos.get('Dr. Doom'))
Clark Kent
None
Computer
Science Science
for k, v in alter_egos.items():
print(k, '=>', v)
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
alpha_num = {}
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
alpha_num = {alpha[i]: i+1 for i in range(0, len(alpha))}
back to Sudoku:
all_units = ([[r+c for c in cols] for r in rows] +
[[r+c for r in rows] for c in cols] +
[[r+c for r in rs for c in cs]
for rs in ('ABC', 'DEF', 'GHI')
for cs in ('123', '456', '789')])
c2_units = units['C2']
Computer
Science Science
c2_units = units['C2']
print(len(c2_peers))
print(c2_peers)
27
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9',
'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2',
'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
Computer
Science Science
27
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9',
'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2',
'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
Problems:
1. List contains duplicate peers
2. List of peers of a square should not
include the square itself ! (C2, above)
Computer
Science Science
Operation Result
x in s tests if x is in set k
s1 ^ s2 returns a new set with elements from either s1 or s2 but not both
Set operations
Computer
Science Science
c2_units = units['C2']
print(len(c2_peers))
print(c2_peers)
27
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9',
'A2', 'B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2',
'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
Computer
Science Science
c2_units = units['C2']
print(len(c2_peers))
print(sorted(c2_peers)) # sorting into list for inspection
20
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C3', 'C4',
'C5', 'C6', 'C7', 'C8', 'C9', 'D2', 'E2', 'F2', 'G2',
'H2', 'I2']
Computer
Science Science
c2_peers = peers['C2']
print(len(c2_peers))
print(sorted(c2_peers))
20
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C3', 'C4',
'C5', 'C6', 'C7', 'C8', 'C9', 'D2', 'E2', 'F2', 'G2',
'H2', 'I2']
Computer
rows = 'ABCDEFGHI' Science Science
cols = '123456789'
def any(iterable):
for element in iterable:
if element:
return True
return False
Computer
Science Science
§Functions
Computer
Science Science
def foo():
pass # special statement -- does nothing!
# (useful as a placeholder)
def bar():
"""Calls foo. This is a function *docstring*.
It should briefly describe what the function
does. I won't always use them in slides, but
you should!"""
foo() # call foo
Computer
Science Science
print(mysum(1, 2))
print(mysum('hello', 'world'))
3
helloworld
Computer
Science Science
def mysum_v2(vals):
"""This version takes a list of vals to add"""
accum = 0 # ← restricts to numbers
for item in vals:
accum += item
return accum
print(mysum_v2([1, 2, 3, 4, 5]))
print(mysum_v2(range(10)))
print(mysum_v2(['hello', 'world']))
15
45
Traceback (most recent call last):
File "[Link]", line 12, in <module>
print(mysum_v2(['hello', 'world']))
File "[Link]", line 7, in mysum_v2
accum += item
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
Computer
Science Science
15
helloworld
(1, 2, 5)
Computer
Science Science
print(mysum_v4([1, 2, 3, 4, 5]))
print(mysum_v4(['hello', 'world'], ''))
print(mysum_v4(['hello', 'world'], start=''))
print(mysum_v4(start='-->', vals=['a', 'b', 'c']))
15
helloworld
helloworld
-->abc
Computer
Science Science
print(mysum_v5(1, 2, 3, 4))
print(mysum_v5('hello', ' ', 'world', start='>'))
10
>hello world
Computer
Science Science
550
Computer
Science Science
print(reduce(add, 1, 2, 3, 4))
print(reduce(add, 'hello', 'world', start=''))
10
helloworld
Computer
Science Science
print(reduce(mult, 1, 2, 3, 4))
print(reduce(mult, 1, 2, 3, 4, start=1))
0
24
Computer
Science Science
add(5, 6) # => 11
mult(5, 6) # => 30
pow_of_2(10) #=> 1024
24
30
19
{8, 9}
Computer
Science Science
is
fun
cakes
ingesting
Computer
Science Science
Got 1 2 3
Got 1 2 3
Got 1 2 3
Computer
Science Science
>>> a = 10
>>> b = a + 10
>>> tmp = a
>>> a = b
>>> b = tmp
>>> (a, b)
(20, 10)
>>> l = [10, 9, 8, 7, 6, '...']
>>> l[-1] = 5
>>> l[len(l):] = [4, 3, 2, 1, 'Bang!']
>>> l
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 'Bang!']
Computer
Science Science
def fibonacci(nth):
a, b = 1, 1
for _ in range(nth-1):
a, b = b, a+b
return a
puzzle = """4.....8.5
.3.......
{'A1': '4',
...7.....
'A2': None,
.2.....6. 'A3': None,
....8.4.. 'A4': None,
....1.... 'A5': None,
...6.3.7. 'A6': None,
5..2..... 'A7': '8',
1.4......""" 'A8': None,
'A9': '5',
...
'I1': '1',
def parse_puzzle(puz): 'I2': None,
puzzle = [c if [Link]() else None 'I3': '4',
for c in puz if c not in ' \n'] 'I4': None,
assert(len(puzzle) == 81) 'I5': None,
return {squares[i]: puzzle[i] 'I6': None,
'I7': None,
for i in range(0, len(squares))}
'I8': None,
'I9': None}
print(parse_puzzle(puzzle))
Computer
Science Science
Demo
Computer
Science Science
def search(sol):
# find a square with the least number of values > 1
#
# (1) "guess" one of the values (assign it) and
# try to solve the rest of the puzzle
#
# (2) if we guessed wrong and the solution is broken,
# backtrack --- i.e., restore the original values
# and guess another value
Computer
Science Science
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
# (1) "guess" one of the values (assign it) and
# try to solve the rest of the puzzle
#
# (2) if we guessed wrong and the solution is broken,
# backtrack --- i.e., restore the original values
# and guess another value
Computer
Science Science
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
assign(sol, sq, val)
search(sol)
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
def search(sol):
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
def search(sol):
if any(not sol[s] for s in squares):
# a square with no values is illegal
return False
elif all(len(sol[s]) == 1 for s in squares):
# if all squares have just one value, we're done
return True
else:
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
orig = [Link]()
for val in orig[sq]:
assign(sol, sq, val)
if not search(sol):
[Link](orig)
else:
break
Computer
Science Science
def search(sol):
if any(not sol[s] for s in squares):
return False
elif all(len(sol[s]) == 1 for s in squares):
return True
else:
sq = min((s for s in squares if len(sol[s]) > 1),
key=lambda s: len(sol[s]))
orig = [Link]()
for val in orig[sq]:
assign(sol, sq, val)
if search(sol):
return True # propagate success back up
else:
[Link](orig)
else:
return False # no guesses worked = earlier fail
Computer
Science Science
Demo
Computer
Science Science
class Point:
pass
p = Point()
p.x = 10
p.y = 20
print('x=', p.x, 'y=', p.y)
x= 10 y= 20
Computer
Science Science
class Point:
def __init__(self): # `self` refers to "this" object
self.x = 10
self.y = 20
p = Point()
print('x=', p.x, 'y=', p.y)
x= 10 y= 20
Computer
Science Science
class Point:
def __init__(self, xinit, yinit):
self.x = xinit
self.y = yinit
p = Point(15, 25)
print('x=', p.x, 'y=', p.y)
x= 15 y= 25
Computer
Science Science
class Point:
...
def translate(self, dx, dy):
self.x += dx
self.y += dy
def dist_to_origin(self):
return sqrt(self.x ** 2 + self.y ** 2)
p = Point(0, 0)
[Link](3, 4)
print('dist of', p, '=', p.dist_to_origin())
def dist_to_origin(self):
return sqrt(self.x ** 2 + self.y ** 2)
p = Point(0, 0)
[Link](p, 4, 3) # same as [Link](4, 3)
print('dist of', p, '=', Point.dist_to_origin(p))
def dist_to_origin(self):
return sqrt(self.x ** 2 + self.y ** 2)
q = Point(0, 0)
r = Point(0, 0)
print(q == r) # based on object identity (reference)
False
Computer
Science Science
class Point:
...
def __eq__(self, other): # called for '=='
if isinstance(other, Point):
return self.x == other.x and self.y == other.y
return NotImplemented
p = Point(10, 20)
q = Point(10, 20)
r = Point(30, 40)
print(p == q)
print(p == r)
print(p == 'hello')
True
False
False
Computer
Science Science
class Point:
...
def __add__(self, other): # called for '+'
if isinstance(other, Point):
return Point(self.x+other.x, self.y+other.y)
return NotImplemented
p = Point(10, 20)
q = Point(10, 20)
r = Point(30, 40)
print(p + q + r)
print(p + 10)
(50,80)
Traceback (most recent call last):
File "[Link]", line 95, in <module>
print(p+10)
TypeError: unsupported operand type(s) for +: 'Point' and 'int'
Computer
Science Science
class Point:
...
def __iter__(self):
yield self.x # ok to not understand this now!
yield self.y # ditto this
p = Point(19, 20)
for coord in p:
print(coord)
l = list(p)
print(l)
cs = [c for c in p]
print(cs)
19
20
[19, 20]
[19, 20]
Computer
Science Science
class Point:
prev_coords = [] # class variable!
p = Point()
q = Point(1, 2)
p = Point()
q = Point(1, 2)
def dist_to_origin(self):
dist2d = super().dist_to_origin()
return sqrt(dist2d ** 2 + self.z ** 2)
p = Point3D(1, 1, 1)
print('dist of', p, '=', p.dist_to_origin())