Review: Lab05 & Hw05
Lab05
停止 yield 的方法:
raise StopIteration
return
def takeWhile(t, p):
for x in t:
if not p(x):
return
yield x
思路:
- 现在是第几轮:
round
- 现在是第
round
轮的第几个:i
round
是偶数 => 跳过round
是奇数 => yield
def backAndForth(t):
round = 0, 1
i, for x in t:
+= 1
i if round % 2 == 1:
yield x
if i == round:
= 0
i round += 1
Cool stuff:
- 我们可以
map
一个list:
def map_list(f, lst):
list(map(f, lst))
- 也可以
map
一个树(期中):
def map_tree(f, t):
return tree(f(label(t)), [map_tree(f, b) for b in branches(t)])
- 自然也可以
map
一个iterator:
def scale(it, multiplier):
yield from map(lambda x: multiplier * x, it)
思路(期中merge_sorted
):
a
和b
的iterator能记住现在到了序列中的第几个- 用
first_a
和first_b
记录a
和b
目前的第一个元素 first_a > first_b
=> 对iter_b
使用next
first_a < first_b
=> 对iter_a
使用next
- 相等,说明出现重复,随便丢掉一个
def merge(a, b):
= next(a), next(b)
first_a, first_b while True:
if first_a == first_b:
yield first_a
= next(a), next(b)
first_a, first_b elif first_a < first_b:
yield first_a
= next(a)
first_a else:
yield first_b
= next(b) first_b
- 写一个 while 版本的算法
- 在必要的时候 yield
def hailstone(n):
yield n
while n != 1:
if n % 2 == 0:
= n // 2
n else:
= n * 3 + 1
n yield n
hailstone(n)
表示从n
开始的 hailstone 数列hailstone(n)
的第一项就是n
- 若
n
是1
,结束 n
是奇数,从第二项起是以n*3+1
为首的 hailstone 数列n
是偶数,从第二项起是以n//2
为首的 hailstone 数列
def hailstone(n):
yield n
if n == 1:
return
elif n % 2 == 0:
yield from hailstone(n // 2)
else:
yield from hailstone(n * 3 + 1)
Hw05
def make_withdraw(balance, password):
history_pw = []
def withdraw(amount, pw):
nonlocal balance
if len(history_pw) >= 3:
return 'Your account is locked. Attempts: {}'.format(history_pw)
if pw != password:
history_pw.append(pw)
return 'Incorrect password'
if amount > balance:
return 'Insufficient funds'
balance -= amount
return balance
return withdraw
关键:
- 旧账户密码不受影响
- 新账户取钱,旧账户也扣
- 新账户输错密码,旧账户也记录
- 新账户的密码得是个正确的密码
def make_joint(withdraw, old_pass, new_pass):
= withdraw(0, old_pass)
error if type(error) == str:
return error
def joint_withdraw(amount, pw):
if pw == new_pass:
return withdraw(amount, old_pass)
return withdraw(amount, pw)
return joint_withdraw
关键:
seq
可以是generator
,因此seq
不一定能+
(群聊)- 但
permutations
yield出来的的一定是list(docstring) - 解法一:无脑全转成list
- 解法二:先算
permutations
,再做拼接
思路:
- 空序列的全排列是空list
- 拿走第一个元素,求剩下的全排列,再把第一个元素拼回去(任意位置)
- 在恰当的时候yield
def permutations(seq):
if not seq:
yield []
else:
= seq[0], seq[1:]
head, tail for perm in permutations(tail):
for i in range(len(seq)):
yield perm[:i] + [head] + perm[i:]
关键:
记下第一棵树上,label为
k
的节点的位置在第二棵树上找到对应的位置,yield节点的label
位置可以是:
preorder的下标(教222/综合楼503)
记录下从root到当前节点每次走了第几个branch
(从广州路门进,先左转再右转…)
用lambda函数编码(见答案)
坑:
刻舟求剑.jpg
= [] lst for i in range(10): lambda : print(i)) lst.append(for f in lst: f()
群里给了一段测试代码
尝试理解答案里
(lookup, i)
做了什么
def lookups(k, key):
if label(k) == key:
yield label
for i in range(len(branches(k))):
for lookup in lookups(branches(k)[i], key):
yield (lambda f, i: lambda v: f(branches(v)[i]))(lookup, i)