谜题 1 保持一致
s = 'Alice' #不能修改字符串s[0] = 'B'
# print默认末尾换行
# end = '' 末尾不换行,加空格
print(s, end=' ')
Python中的列表(list)可理解为元素的序列或数组
L = [1, 2, 'A', [3,4] ]
元组与列表类似但不可修改
T1 = (1, 2, 'A', [3, 4] )
T2= (1, 2, 'A', (3, 4) )
T1[3]不可修改,T1[3][0]可修改
T2[3][0]不可修改
习题
cap1 = ['F', 'F', 'B', 'B', 'B', 'F', 'B', 'B', 'B', 'F', 'F', 'B', 'F'] cap2 = ['F', 'F', 'B', 'B', 'B', 'F', 'B', 'B', 'B', 'F', 'F', 'F', 'F'] cap3 = ['F', 'F', 'B', 'H', 'B', 'F', 'B', 'B', 'B', 'F', 'H', 'F', 'F']
习题 1.修改代码使命令听起来更自然一些。
增加判断语句,输出时先判断区间大小是否为1
def pleaseConform(caps): start = forward = backward = 0 intervals = [] #caps += ['end'] for i in range(1, len(caps)): if caps[start] != caps[i] or i == len(caps) - 1: intervals.append((start, i - 1, caps[start])) if caps[start] == 'F': forward += 1 else: backward += 1 start = i if forward < backward: flip = 'F' else: flip = 'B' for t in intervals: if t[2] == flip: if t[0] == t[1]: print('People in positions', t[0], 'flip your caps!') else: print('People in positions', t[0], 'through', t[1], 'flip your caps!')
习题2.修改pleaseConformOnepass,如习题1那样打印更自然一些的命令,并确保程序再输入是空列表时不会崩溃。
提示:你需要记住区间的起始位置(而不是在第6行打印)。
记录开始位置,输出时先判断区间大小是否为1
def pleaseConformOnepass(caps): if caps != []: caps = caps + [caps[0]] for i in range(1, len(caps)): if caps[i] != caps[i - 1]: if caps[i] != caps[0]: start = i else: if start == i-1: print('People in positions', i-1, 'flip your caps!') else: print('People in positions', start, ' through', i - 1, 'flip your caps!') pleaseConformOnepass(cap2)
习题3.
假设在队伍中存在没戴帽子的人。我们用字符’H’代表他们。例如,有这样一组数据:
caps3 = [‘F’, ‘F’, ‘B’, ‘H’, ‘B’, ‘F’, ‘B’, ‘B’, ‘B’, ‘F’, ‘H’, ‘F’, ‘F’ ]
我们不想指示没戴帽子的人去转动不存在的帽子,这令人困惑,可能会导致有人试图从队伍前面的人那里偷帽子。因此我们希望跳过所有’H’位置。修改pleaseConform,使它生成正确并且最小数量的命令集合。对于上面的例子,它应当生成:
People in positions 2 flip your caps!
People in positions 4 flip your caps!
People in positions 6 through 8 flip your caps!
增加对不戴帽子 'H' 的判断
def pleaseConform(caps): start = forward = backward = 0 intervals = [] #caps += ['end'] for i in range(1, len(caps)): if caps[start] != caps[i] or i == len(caps) - 1: if caps[start] != 'H': intervals.append((start, i - 1, caps[start])) if caps[start] == 'F': forward += 1 else: backward += 1 start = i if forward < backward: flip = 'F' else: flip = 'B' for t in intervals: if t[2] == flip: if t[0] == t[1]: print('People in positions', t[0], 'flip your caps!') else: print('People in positions', t[0], 'through', t[1], 'flip your caps!') pleaseConform(cap3)
习题4 写一段程序实现简单的游程编码,将给定字符串(如BWWWWWBWWWW)转换为较短的字符串(1B5W1B4W),并且执行游程解码,将压缩过的字符串转换回原始字符串。你只能通过一次字符串遍历来执行压缩和解压缩过程。
str函数能将数字转换成字符串,例如str(12) = ‘12’。它在编码步骤汇总会很有用。
int函数能将字符串转换成数字,例如:int(‘12’) = 12。对于任意字符串s,如果s[i]是字母字符,则s[i].isalpha()将返回True,否则返回False。如果s中所有的字符都是字母字符,则s.isalpha()返回True,否则返回False。函数int和isalpha在解码步骤中会很有用。
s = "BWWWWWBWWWWQ" def encode(string): string += ' ' time = idx = 1 res = '' while idx < len(string): if string[idx] != string[idx - 1]: res += str(time) res += string[idx - 1] time = 1 else: time += 1 idx += 1 print(res) return res def decode(string): time = 0 res = '' for c in string: if '0' <= c <= '9': time = time * 10 + int(c) else: for i in range(time): res += c time = 0 print(res) return res decode(encode(s))
谜题 2 参加派对的最佳时间
#选择排序 def sortList(tlist): for ind in range(len(tlist) - 1): iSm = ind for i in range(ind, len(tlist)): if tlist[iSm][0] > tlist[i][0]: iSm = i tlist[ind], tlist[iSm] = tlist[iSm], tlist[ind]
习题1
在计算名人参加派对最多的时间时,增加对时间是否满足[ystart, yend]范围的判断
sched2 = [(6.0, 8.0), (6.5, 12.0), (6.5, 7.0), (7.0, 8.0), (7.5, 10.0), (8.0, 9.0), (8.0, 10.0), (9.0, 12.0), (9.5, 10.0), (10.0, 11.0), (10.0, 12.0), (11.0, 12.0)] def bestTimeToPartySmart(schedule, ystart, yend): times = [] for c in schedule: times.append((c[0], 'start')) times.append((c[1], 'end')) sortlist(times) maxcount, time = chooseTime(times, ystart, yend) print(maxcount, time) # 选择排序 def sortlist(tlist): for ind in range(len(tlist) - 1): iSm = ind for i in range(ind, len(tlist)): if tlist[iSm][0] > tlist[i][0]: iSm = i tlist[ind], tlist[iSm] = tlist[iSm], tlist[ind] return def chooseTime(times, ystart, yend): rcount = 0 maxcount = 0 time = 0 # Range through the times computing a running count of celebrities for t in times: if t[1] == 'start': rcount = rcount + 1 elif t[1] == 'end': rcount = rcount - 1 if rcount > maxcount and ystart < t[0] < yend: maxcount = rcount time = t[0] return maxcount, time ##bestTimeToPartySmart(sched) ystart = 8 yend = 10 bestTimeToPartySmart(sched2, ystart, yend)
习题2
有另一种方法, 可以不依赖时间精度来计算参加派对的最佳时间。我们依次选择每位名人的时间区间,并确定有多少其他名人的时间区间包含所选名人的开始时间。我们选择出某位名人,使他的开始时间被最大数量的其他名人时间区间所包含,并将他的开始时间作为参加派对的时间。编写代码实现该算法,并验证它的结果与基于排序算法的结果是否相同。
计算每一位名人在开始时间时,有多少其它名人在场
def fun2(time): max_count = count = 0 best_time = 0; for t in time: for t0 in time: if t0[0] <=t[0] < t0[1] : count += 1 if max_count < count: max_count = count best_time = t[0] return best_time, max_count
习题3
假设每位名人都有一个权重,取决于你对这位名人的喜爱程度。可以在时间表中将其表示为一个三元组,如(6.0, 8.0, 3)。开始时间是6.0,结束时间是8.0,权重是3。修改代码,找出最大化名人总权重的时间。例如…下面是一个更复杂的例子:
sched3 = [(6.0, 8.0, 2), (6.5, 12.0, 1), (6.5, 7.0, 2), (7.0, 8.0, 2), (7.5, 10.0, 3), (8.0, 9.0, 2), (8.0, 10.0, 1), (9.0, 12.0, 2), (9.5, 10.0, 4), (10.0, 11.0, 2), (10.0, 12.0, 3), (11.0, 12.0, 7)]
根据名人的日程安排,你想要在11点参加派对,此时参加派对名人权重之和是13,为最大值。
对2.2的算法进行修改:
在排序时间前,即bestTimeToPartySmart函数中,对每一个开始时间和结束时间都记录上该名人的权重值
在最终选择时间时,即chooseTime函数中,“start” 时刻将增加此名人对应的权重,“end” 时刻减少权重
sched3 = [(6.0, 8.0, 2), (6.5, 12.0, 1), (6.5, 7.0, 2), (7.0, 8.0, 2), (7.5, 10.0, 3), (8.0, 9.0, 2), (8.0, 10.0, 1), (9.0, 12.0, 2), (9.5, 10.0, 4), (10.0, 11.0, 2), (10.0, 12.0, 3), (11.0, 12.0, 7)] def bestTimeToPartySmart(schedule): times = [] for c in schedule: times.append((c[0], 'start', c[2])) times.append((c[1], 'end', c[2])) sortlist(times) maxcount, time = chooseTime(times) return maxcount, time # 选择排序 def sortlist(tlist): for ind in range(len(tlist) - 1): iSm = ind for i in range(ind, len(tlist)): if tlist[iSm][0] > tlist[i][0]: iSm = i tlist[ind], tlist[iSm] = tlist[iSm], tlist[ind] return def chooseTime(times): rcount = 0 maxcount = 0 time = 0 # Range through the times computing a running count of celebrities for t in times: if t[1] == 'start': rcount = rcount + t[2] elif t[1] == 'end': rcount = rcount - t[2] if rcount > maxcount: maxcount = rcount time = t[0] return maxcount, time maxcount, time = bestTimeToPartySmart(sched3) print('The best time to go is', time, 'with pow', maxcount)
参考资料:
编程的乐趣用Python解算法谜题 —— 斯里尼·德瓦达斯
编程的乐趣:用Python解算法谜题 课后习题答案 —— CSDN博主「咬不动的椰果」:https://blog.csdn.net/qgazq/article/details/102711260