目录
昨天有一个留学生朋友问了我一到python题,题目如下:
原题目
Besides a function to generate a random dictionary,defines two functions that analyse a dictionary.See the pdf for explanations via an illustrationand examples of possible uses.
You can assume that both functions are called with proper arguments (namely, a dictionary whose keys are all integers between 1 and n for some strictly positive integer n and whose values are numbers between 1 and n,and an integer between 1 and n).
The lines that are output by the function longest_strictly_decreasing_sequences_to() are ordered from smallest first value to largest first value.
题目翻译
除了生成随机字典的函数外,还定义了两个分析字典的函数。请参阅 pdf 以通过插图和可能使用的示例进行解释。 您可以假设这两个函数都使用适当的参数调用(即,对于某些严格的正整数 n,其键都是 1 和 n 之间的整数,其值是 1 和 n 之间的数字,以及 1 和 n 之间的整数)。 #函数longest_strictly_decreasing_sequences_to() 输出的行从最小的第一个值到最大的第一个值排序。
题目给出的模板
from random import seed, randint
def generate_mapping(for_seed, length):
seed(for_seed)
return {i: randint(1, length) for i in range(1, length + 1)}
def follow_the_arrows_from(mapping, n):
pass
# REPLACE PASS ABOVE WITH YOUR CODE
def longest_strictly_decreasing_sequences_to(mapping, n):
if n not in mapping.values():
return
题目分析
需要实现两个函数
def follow_the_arrows_from(mapping, n):
...
def longest_strictly_decreasing_sequences_to(mapping, n):
...
第一个函数是用种子生成一个字典
mapping = generate_mapping(30, 12)打印结果如下
{1: 9, 2: 5, 3: 10, 4: 1, 5: 10, 6: 11, 7: 4, 8: 5, 9: 1, 10: 7, 11: 7, 12: 11}
根据生成的mapping运行第二个函数:
输出的语句里可以理解为:第一句是陷入循环需要几步,第二句是循环有多长。
第三个函数实现,输入n,输出最长路径,如上面的字典,输入1其对应的键有4和9;4作为值对应的键有7,9作为值对应的键有1,1小于9,到头第二条路经是9 ->1;7作为值对应的键有10和11,10作为值对应的键有5,5小于10到头,路径10->7->1,11作为值对应的键为12,到头,路径12 -> 11 -> 7 -> 4 -> 1,输出这条最长路径。
解答过程
这里我认为可以用列表储存每次路过的值然后判断是否循环,代码如下:
def follow_the_arrows_from(mapping, n):
li = [n]
temp = n
while True:
n = mapping[n]
if n not in li:
li.append(n)
else:
if n == temp:
print(f'It is on a loop of length {len(li)}')
break
else:
print(f'It starts with a stalk of length {li.index(n)}')
print(f'It reaches {n} on a loop of length {len(li) - li.index(n)}')
break
第一个比较简单,下面看第二个,完整代码
#函数longest_strictly_decreasing_sequences_to() 输出的行从最小的第一个值到最大的第一个值排序。
def longest_strictly_decreasing_sequences_to(mapping, n):
if n not in mapping.values():
return
lis = []
# lis_end = []
for i in range(len(mapping), 0, -1): # 倒序循环
li = []
# path_num = mapping[i]
while n <= mapping[i] < i: # 判断该键对应的值是否小于键,且大于或等于n
li.append(i) # 满足条件加入列表
i = mapping[i] #将该值作为新键进行下一轮判断
# 当结束上一循环获得一个列表时进入下一个判断
if len(li) != 0 and i == n: # 如果这个列表非空,且最后的值等于n,满足条件
li += [n] # 将n加入列表
lis.append(li) # 将li加入满足条件最终值为n的列表集
for li in lis:
if len(li) == len(max(lis)): # 最长路径可能有多个,判断是不是最长路径
s1 = ' -> '.join(str(n) for n in sorted(li, reverse=True))
print(s1) # 输出最长路径
这个方法是倒着遍历字典,然后判断最终指向的值是不是n,如果是n就保存到列表里,把所有符合的列表保存到二位列表,最后判断最长的几个输出。
测试输出
mapping = generate_mapping(30, 12)
print(mapping)
follow_the_arrows_from(mapping, 6)
follow_the_arrows_from(mapping, 4)
longest_strictly_decreasing_sequences_to(mapping, 1)
longest_strictly_decreasing_sequences_to(mapping, 7)
输出结果:
{1: 9, 2: 5, 3: 10, 4: 1, 5: 10, 6: 11, 7: 4, 8: 5, 9: 1, 10: 7, 11: 7, 12: 11}
It starts with a stalk of length 4
It reaches 1 on a loop of length 2
It starts with a stalk of length 1
It reaches 1 on a loop of length 2
12 -> 11 -> 7 -> 4 -> 1
12 -> 11 -> 7
不过,题目下方还给出了一个提示:
# Hint: create a dictionary, D, whose keys are the # numbers i in the interval [n + 1, len(mapping)] # such that there is a path from i to n, with as # corresponding value the length of this path. # max(D.values()) evaluates to the largest length # of those paths; let M denote that value. # For each number i in the interval [n + 1, len(mapping)], # if i is a key of D and M is the associated value, then # output i, mapping[i], mapping[mapping[i]], ..., n, # separating consecutive values with ->. # INSERT YOUR CODE HERE提示:创建一个字典 D,其键是区间 [n + 1, len(mapping)] 中的数字 i,使得存在从 i 到 n 的路径,对应的值是该路径的长度。 max(D.values()) 计算这些路径的最大长度;让 M 表示该值。对于区间 [n + 1, len(mapping)] 中的每个数 i,如果 i 是 D 的键,M 是关联值,则输出 i, mapping[i], mapping[mapping[i]], . .., n, 用 -> 分隔连续值。
感觉略麻烦,没有试,有兴趣的朋友可以试一下。
完整代码
quiz.py
from random import seed, randint
def generate_mapping(for_seed, length):
seed(for_seed)
return {i: randint(1, length) for i in range(1, length + 1)}
def follow_the_arrows_from(mapping, n):
li = [n]
temp = n
while True:
n = mapping[n]
if n not in li:
li.append(n)
else:
if n == temp:
print(f'It is on a loop of length {len(li)}')
break
else:
print(f'It starts with a stalk of length {li.index(n)}')
print(f'It reaches {n} on a loop of length {len(li) - li.index(n)}')
break
# REPLACE PASS ABOVE WITH YOUR CODE
def longest_strictly_decreasing_sequences_to(mapping, n):
if n not in mapping.values():
return
lis = []
# lis_end = []
for i in range(len(mapping), 0, -1): # 倒序循环
li = []
# path_num = mapping[i]
while n <= mapping[i] < i: # 判断该键对应的值是否小于键,且大于或等于n
li.append(i) # 满足条件加入列表
i = mapping[i] #将该值作为新键进行下一轮判断
# 当结束上一循环获得一个列表时进入下一个判断
if len(li) != 0 and i == n: # 如果这个列表非空,且最后的值等于n,满足条件
li += [n] # 将n加入列表
lis.append(li) # 将li加入满足条件最终值为n的列表集
for li in lis:
if len(li) == len(max(lis)): # 最长路径可能有多个,判断是不是最长路径
s1 = ' -> '.join(str(n) for n in sorted(li, reverse=True))
print(s1) # 输出最长路径
test.py
from quiz import *
mapping = generate_mapping(30, 12)
print(mapping)
follow_the_arrows_from(mapping, 6)
follow_the_arrows_from(mapping, 4)
longest_strictly_decreasing_sequences_to(mapping, 1)
longest_strictly_decreasing_sequences_to(mapping, 7)