【个人笔记】编程的乐趣(用python解算法谜题)——谜题1,2
谜题 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

浙公网安备 33010602011771号