This lab provides practice defining generator functions, importing modules, and using sorting and string functions.
Instructions:
Modify this notebook by adding the Python code described below.
Test your code using the menu item Cell ► Run All
Save the notebook (the .ipynb file) and upload it to the appropriate Assignment folder on the course web site.
Write a generator function named vowelsfrom(s)
that takes a string argument and returns a generator that returns successive vowels from the string s
. No other characters should be returned. For this problem, vowels include only a, e, i, o and u.
For example, vowelsfrom('orangutan')
would return an generator that returns 'o'
, 'a'
, 'u'
and 'a'
on successive calls.
def vowelsfrom(s):
while s:
c,s = s[0],s[1:]
if c in 'aeiou':
yield c
list(vowelsfrom('orangutan'))
['o', 'a', 'u', 'a']
Based on the descriptions of the standard Python packages in:
https://docs.python.org/3.10/library/index.html
create a tuple named modules
containing six strings that are the names of the six modules that include functions to:
For example, if this question asked for the names of the two modules that contained: (1) mathematical functions for complex numbers and (2) functions for working with zip files the definition would be:
modules=('cmath', 'zipfile')
modules=("math", "random", "datetime", "json", "csv", "itertools")
Write a function hours2go(t)
that returns a floating point number that is the number of hours between the datetime
object t
and 00:00:00 on January 1, 2000. If this value is negative the function should return 0. The value should be accurate to 1/3600 (one second).
For example, hours2go(datetime.datetime(1999, 12, 31, 20, 0, 36))
would return 3.99
import datetime
def hours2go(t):
return (datetime.datetime(2000, 1, 1) - t).total_seconds()/3600.
hours2go(datetime.datetime(1999, 12, 31, 20, 0, 36))
3.99
Write a function criticals(l,n)
that is passed a list of complex number l
and an integer n
and returns a list of the n
values from l
whose magnitudes are closest to 1 in order of increasing distance from the unit circle.
In the following diagram, the distance from complex value P1 to the unit circle is d1 which is less than the distance d2 for P2):
For example, critical([0+0j, 2+0j, 0.7+0.7j, 0.5+0j, -1+0j],3)
would return (-1+0j), (0.7+0.7j), (0.5+0j)
.
def critical(l,n):
return sorted(l,key=lambda x:abs(abs(x)-1))[0:n]
critical([0+0j, 2+0j, 0.7+0.7j, 0.5+0j, -1+0j],3)
[(-1+0j), (0.7+0.7j), (0.5+0j)]
Write a function strexpansion(s)
that returns the ratio of the number of bytes required for the UTF-8 encoding of the string s
and the number of characters in s
.
For example, strexpansion('RÖ猫𐒎')
would return 2.5.
def strexpansion(s):
return float(len(s.encode()))/len(s)
strexpansion('RÖ猫𐒎')
2.5
# lab validation code; do not modify
def labcheck():
import copy, random, re, string, types
from random import randint
def checkre(pat,ok,nok):
for s in ok:
assert re.fullmatch(pat,s), \
f"pattern '{pat}'\n did not match string '{s}'"
for s in nok:
assert not re.fullmatch(pat,s), \
f"pattern '{pat}'\n matched string '{s}'"
def randwords(n,chars=string.ascii_lowercase,nl=(2,5)):
l = set()
while len(l)<n:
l |= set((''.join([chars[randint(0,len(chars)-1)] for i in range(randint(*nl))]),))
return list(l)
def q1():
import types
s = randwords(1,nl=(15,20))[0]
os = copy.deepcopy(s)
r = vowelsfrom(s)
tv, tg = type(vowelsfrom), type(r)
assert tv == types.FunctionType and tg == types.GeneratorType, \
f"vowelsfrom is a {tv} that returns a {tg} (must be function that returns a generator)"
rs = [c for c in r]
assert rs == [c for c in s if c in 'aeiou'], \
f"iterating through vowelsfrom('{os}') returns {rs}"
def q2():
assert len(modules) == 6, f"modules has {len(modules)} elements"
hashvalues= (
'7a488390a939c4795cc1a801e51751d5f25d800d',
'a415ab5cc17c8c093c015ccdb7e552aee7911aa4',
'89ffad089c042f31dcc81269da38bef3ca44ab1f',
'05d97e6e9834ccf063c552e404b9ecafc5e4d662',
'6cc981744e5c893179434506139a3107851b061e',
'9e9cf1097fbb8c0af843641c0e32781c81ce4931',)
import hashlib
for i,s in enumerate(modules):
h = hashlib.sha1()
h.update(bytes(s,'utf-8'))
#print(s,h.hexdigest())
assert h.hexdigest() == hashvalues[i], \
f"modules[{i}] ({s}) is not right"
def q3():
dt = random.random()*3600*100
t = datetime.datetime(2000, 1, 1) - datetime.timedelta(seconds=dt)
rt = hours2go(t)*3600
assert abs(dt - rt) < 1/3600, f"hours2go({t}) returns {rt/3600}"
def q4():
d = lambda c:abs(abs(c)-1)
n = randint(2,4)
nn = n + randint(1,4)
l = [complex(*(2*random.random() for i in range(2))) for i in range(nn)]
on, ol = copy.deepcopy(n), copy.deepcopy(l)
rl = critical(l,n)
# check for n outputs
c1 = len(rl) == n
# check that outputs are in order
c2 = all( [d(rl[i]) < d(rl[i+1]) for i in range(len(rl)-1)] )
# check that largest output is smaller than un-returned inputs
c3 = all( [d(x) > d(rl[n-1]) for x in set(ol) - set(rl)] )
assert c1 and c2 and c3, f"critical({ol},{n}) returns {rl}"
def q5():
s = ''
nb = 0
for i,(a,b) in enumerate([(0x41,0x7e),(0x100,0x13f),(0x4e01,0x4e13)]):
l = [chr(c) for c in range(a,b)]
n = randint(3,5)
s += ''.join(random.sample(l,n))
nb += n*(i+1)
os = copy.deepcopy(s)
rf = strexpansion(s)
assert float(nb)/len(os) == rf, \
f"strexpansion('{os}') returns {rf}"
for s,i in [(s,s[1:]) for s in locals().keys() if re.search(r'q\d+',s)]:
try:
locals()[s]()
print(f"Question {i} OK.")
except Exception as e:
print(f"Failed check for Question {i}: {e}")
labcheck()
Question 1 OK. Question 2 OK. Question 3 OK. Question 4 OK. Question 5 OK.