在我看来,最简单的解决方案是这里的for 循环,因为从根本上说您想要的是迭代。您还可以使用enumerate 跟踪当天:
sample_steps = [("2010-01-1", 1),
("2010-01-2", 3),
("2010-01-3", 5),
("2010-01-4", 7),
("2010-01-5", 9),
("2010-01-6", 11)]
def days_to_reach_n_steps(step_records, n):
total_steps = 0
for counter, (date, steps) in enumerate(step_records, 1):
total_steps += steps
if total_steps >= n:
return counter, date
我选择了奇数作为步骤的顺序,因为它们的累积和是平方(更容易用肉眼检查):
for boundary in range(1, 7):
for steps in range(boundary ** 2 - 1, boundary ** 2 + 2):
result = days_to_reach_n_steps(sample_steps, steps)
if result:
days, date = result
print("{} steps in {} days (arrived at {})".format(steps, days, date))
else:
print("{} was unreached".format(steps))
这将返回:
0 steps in 1 days (arrived at 2010-01-1)
1 steps in 1 days (arrived at 2010-01-1)
2 steps in 2 days (arrived at 2010-01-2)
3 steps in 2 days (arrived at 2010-01-2)
4 steps in 2 days (arrived at 2010-01-2)
5 steps in 3 days (arrived at 2010-01-3)
8 steps in 3 days (arrived at 2010-01-3)
9 steps in 3 days (arrived at 2010-01-3)
10 steps in 4 days (arrived at 2010-01-4)
15 steps in 4 days (arrived at 2010-01-4)
16 steps in 4 days (arrived at 2010-01-4)
17 steps in 5 days (arrived at 2010-01-5)
24 steps in 5 days (arrived at 2010-01-5)
25 steps in 5 days (arrived at 2010-01-5)
26 steps in 6 days (arrived at 2010-01-6)
35 steps in 6 days (arrived at 2010-01-6)
36 steps in 6 days (arrived at 2010-01-6)
37 was unreached
请注意,days_to_reach_n_steps 只有一个return 语句,但仍设法将return None 用于37。这是因为一个不返回任何内容的函数隐含地返回None。但是,这与您对 0 的规范不太匹配。如果您希望 0 异常,我建议您这样做:
for counter, (date, steps) in enumerate([("start", 0)] + step_records):
答案的第一行会变成
0 steps in 0 days (arrived at start)
这维护了算法的其余部分,因此您无需编写边缘情况。
如果它必须是一个while循环,你可以稍微滑稽地把for循环改写成这样:
def days_to_reach_n_steps(step_records, n):
total_steps = 0
counter = 0
step_records = [("start", 0)] + step_records
while counter < len(step_records):
date, steps = step_records[counter]
total_steps += steps
if total_steps >= n:
return counter, date
counter += 1
这与 for 循环方法的第二次迭代完全相同($ diff <(python while.py) <(python code.py) 干净地退出)。
要使其类似于 for 循环的第一次迭代,请删除对 step_records 的重新分配并返回 counter + 1。
请注意,这并不是一个很好的 while 循环应用程序——也许是为了练习使用 while 循环,但我真的不赞成强制使用丑陋的代码——Python 已经有简单的习惯用法来迭代列表和保持索引。见the Zen of Python。