【选修课】Python 实现-附ChatGPT解析

1.题目

现有两门选修课,每门选修课都有一部分学生选修,每个学生都有选修课的成绩,需要你找出同时选修了两门选修课的学生先按照班级进行划分,班级编号小的先输出,每个班级按照两门选修课成绩和的降序排序,成绩相同时按照学生的学号升序排序
输入描述
第一行为第一门选修课学生的成绩
第二行为第二门选修课学生的成绩,每行数据中学生之间以英文分号分隔,每个学生的学号和成绩以英文逗号分隔,学生学号的格式为8位数字(2位院系编号+入学年份后2位+院系内部1位专业编号+所在班级3位学号),学生成绩的取值范用为[0.100]之间的整数,两门选修课选修学生数的取值范围为[1-2000]之间的整数

输出描述
同时选修了两门选修课的学生的学号,如果没有同时选修两门选修课的学生输出NULL,否则,先按照班级划分,班级编号小的先输出,每个班级先输出班级编号(学号前五位),然后另起一行输出这个班级同时选修两门选修课的学生学号,学号按照要求排序(按照两门选修课成绩和的降序,成绩和相同时按照学号升序),学生之间以英文分号分隔。

示例1
输入:

01202021,75;01201033,95;01202008,80;01203006,90;01203088,100
01202008,70;01203088,85;01202111,80;01202021,75;01201100,88
输出:
01202
01202008;01202021
01203
01203088
说明:
同时选修了两门选修课的学生01202021、01202008、01203088,
这三个学生两门选修课的成绩和分别为150、150、185,
其中学号为01202021、01202008的,属于01202班的学生,然后按照成绩和降序,成绩同时按学号升席输出的结果为01202008、01202021,
01203088属于01203班的学生,按照成绩和降序,成绩相同时按学号升序输出的结果为01203088,
01202的班级编号小于01203的班级编号,需要先输出。

示例2:
01201022,75;01202033.95;01202018.80;01203006.90;01202066,100
01202008,70;01203102,85;01202111,80;01201021,75;01201100,88
输出:
NULL
说明:没有同时选修了两门选修课的学生,输出NULL。

2.解析

题目要求找出同时选修了两门选修课的学生,并按照以下规则进行排序和输出:

  1. 首先按照班级编号升序排序学生数据。
  2. 在同一个班级内,将学生学号使用分号分隔。
  3. 不同班级之间使用换行符分隔。
  4. 学生的排序规则为:首先按照两门选修课成绩和的降序排序,成绩和相同时按照学号升序排序。
  5. 如果没有同时选修两门选修课的学生,则输出"NULL"。

Q:sorted_common_students = sorted(common_students.items(), key=lambda x: (x[0][:5], -x[1], x[0]))这句代码什么意思

这行代码是用来对学生数据进行排序的。

  • sorted_common_students: 这是一个函数 sorted() 的调用,用来对待排序的学生数据进行排序,并将结果存储在一个列表中。
  • common_students.items(): 这部分将字典 common_students 中的键值对转换成一个包含元组的列表,每个元组包含学生的学号和成绩和,例如 [(学号1, 成绩和1), (学号2, 成绩和2), …]。
  • key=lambda x: (x[0][:5], -x[1], x[0]): 这是排序的关键函数,它定义了如何对元素进行排序。这里的 x 代表元组列表中的每一个元组,x[0] 表示学号,x[1] 表示成绩和。
    • x[0][:5] 表示取学号的前五位,也就是班级编号部分。这是排序的第一关键条件,它会按照班级编号升序排列。
    • -x[1] 表示成绩和的相反数,即成绩和的降序排列。这是排序的第二关键条件,它会按照成绩和降序排列。
    • x[0] 表示学号本身。这是排序的第三关键条件,它会在前两个条件相同时按照学号升序排列。
      \

综合起来,这行代码的作用是将学生数据按照班级编号升序排列,同一班级内的学生按照成绩和的降序排列,成绩和相同时按照学号升序排列。

3.代码

解题思路如下:

  1. 首先,我们需要解析输入数据,分别获得两门选修课的学生成绩学生学号,将它们存储在字典map中,其中键为学号,值为成绩
  2. 接下来,我们需要查找同时选修了两门选修课的学生
    我们遍历第一门选修课的学生,检查是否存在于第二门选修课的学生中
    如果存在,我们计算两门选修课的成绩和
    并将这些学生的学号和成绩和存储在一个新的字典中。
  3. 如果没有找到同时选修两门选修课的学生,我们输出"NULL"。
  4. 如果找到了同时选修两门选修课的学生,我们需要按照题目要求进行排序和输出。
    首先,我们按照班级编号升序排序学生数据。
    然后,在同一个班级内,将学生学号使用分号分隔。
    最后,不同班级之间使用换行符分隔。
    在同一个班级内,学生的排序规则为:首先按照两门选修课成绩和的降序排序,成绩和相同时按照学号升序排序。
  5. 最终,我们将排好序的学生数据按照规定的格式输出。

Q. ‘for student_id, total_score in sorted_common_students:’ 这段for循环下的代码运行思路

  1. sorted_common_students 是一个已排序的学生数据列表,其中每个元素都是一个包含学生学号和成绩和的元组。
  2. for student_id, total_score in sorted_common_students: 这个 for 循环遍历了 sorted_common_students 中的每个元素。
  3. 对于每个元素,解包操作将学生的学号赋给 student_id,将两门选修课成绩和赋给 total_score。
  4. 接下来,代码会根据当前的学生数据执行以下操作:
  • 检查学生的班级编号,如果与上一个学生的班级编号不同,则表示进入了新的班级。在这种情况下,将上一个班级的学生学号使用分号分隔并添加到输出结果中,并添加新班级的班级编号
  • 然后,将当前学生的学号添加到当前班级的学生列表中
  • 最后,将当前的班级编号更新为新的班级编号,并继续处理下一个学生。
  1. 循环继续迭代下一个元素,重复上述操作,直到遍历完整个 sorted_common_students 列表。
  2. 循环结束后,可能会有最后一个班级的学生数据未添加到输出结果中。因此,在循环结束后,检查是否存在当前班级的学生列表,如果存在,将其中的学号使用分号分隔并添加到输出结果中。
  3. 最终,生成的输出结果中包含了同一个班级的多个学生学号,使用分号分隔,不同班级之间使用换行符分隔,满足了题目的要求。

这个 for 循环的目的是根据排序后的学生数据生成最终的输出结果,确保输出格式和顺序符合题目要求。

# 解析输入数据并执行任务
def find_students_with_both_courses(students1,students2):
    common_students = {}  # 保存同时选修两门选修课的学生的学号和成绩和

    # 查找同时选修两门选修课的学生
    for student_id, score1 in students1.items():
        if student_id in students2:
            total_score = score1 + students2[student_id]
            common_students[student_id] = total_score

    if not common_students:  # 如果没有同时选修两门选修课的学生
        return "NULL"

    # 根据班级编号升序排序学生数据
    sorted_common_students = sorted(common_students.items(), key=lambda x: (x[0][:5], -x[1], x[0]))

    result = []  # 存储输出结果

    current_class = ""  # 当前班级编号
    current_students = []  # 当前班级的学生列表
    for student_id, total_score in sorted_common_students:
        class_id = student_id[:5]  # 提取班级编号
        if class_id != current_class:
            if current_students:
                result.append(";".join(current_students))  # 添加同一个班级的学生学号,使用分号分隔
            result.append(class_id)
            current_class = class_id
            current_students = []
        current_students.append(student_id)

    # 添加最后一个班级的学生学号
    if current_students:
        result.append(";".join(current_students))

    # 将不同班级之间使用换行符分隔
    formatted_result = "\n".join(result)
    return formatted_result

# 主程序
if __name__ == "__main__":
    # 解析第一门选修课学生的成绩
    scores1 = input().split(';')
    students1 = {student_id: int(score) for student_id, score in map(lambda x: x.split(','), scores1)}
    #print('students1:',students1)

    # 解析第二门选修课学生的成绩
    scores2 = input().split(';')
    students2 = {student_id: int(score) for student_id, score in map(lambda x: x.split(','), scores2)}
    #print('students2:',students2)

    result = find_students_with_both_courses(students1,students2)  # 执行任务
    print(result)  # 输出结果

'''
输入
01202021,75;01201033,95;01202008,80;01203006,90;01203088,100
01202008,70;01203088,85;01202111,80;01202021,75;01201100,88

输出
01202
01202008;01202021
01203
01203088
'''

你可能感兴趣的:(Python刷题,python,华为od)