用Pandas解决大学课程约束满足问题

slsn1g29  于 2023-10-14  发布在  其他
关注(0)|答案(1)|浏览(80)

我有一个包含一些大学课程的电子表格。

  • 每个课程都有pre-requisitesco-requisites,其中pre-requisites是在能够注册特定课程之前应该通过的课程。
  • Co-requisites是指参加课程之前应该通过的课程,或者可以与我们期待注册的课程在同一学期**注册的课程。

例如,这是我的一部分。
| 课程名称|预处理|公司简介|
| --|--|--|
| 微积分A|||
| 微积分B|微积分A||
| 线性代数|||
| 微积分C|【微积分B、线性代数】||
| 微分方程|线性代数|微积分C|
| 计算机编程|【微积分A、线性代数】||
| Physics A||微积分A|
| 物理A实验室||Physics A|
| 物理学B| Physics A||
| 物理B实验室|物理A实验室|物理学B|
| 电气电路|物理学B|微分方程|
| 电路实验室|物理B实验室|电气电路|
| 数字逻辑|[计算机程序设计、电路、电路实验室]||
| 数字逻辑实验室||数字逻辑|
我涵盖了所有的案件。

  • 有些课程没有pre-requisitesco-requisites,如Calculus A
  • 此外,还有一些课程有co-requisites,但没有pre-requisites,如Digital Logic Lab
  • 此外,还有一些课程是co-requisites链,如Electrical Circuits Lab,要求您通过Electrical Circuits或在同一学期注册。
  • 所以,如果你只通过了Physics BPhysics B LabCalculus BLinear Algebra,而你想注册Electrical Circuits Lab,那么你需要在同一学期注册Calculus CDifferential EquationsElectrical Circuits
  • 最后,为了简单起见,一个course只有0或1个co-requisite(s)。

我需要一个解决方案,我可以给予一个输入,这是通过的课程,我得到一个输出,这是可以注册的课程。
以下是我的课程数据源(courses.csv)的一部分:

course_name,pre_requisites,co_requisite
Calculus-A,,
Calculus-B,Calculus-A,
Linear-Algebra,,
Calculus-C,Calculus-B_Linear-Algebra,
Differential-Equations,Linear-Algebra,Calculus-C
Computer-Programming,Calculus-A_Linear-Algebra,
Physics-A,,Calculus-A
Physics-A-Lab,,Physics-A
Physics-B,Physics-A,
Physics-B-Lab,Physics-A-Lab,Physics-B
Electrical-Circuits,Physics-B,Differential-Equations
Electrical-Circuits-Lab,Physics-B-Lab,Electrical-Circuits
Digital-Logic,Computer-Programming_Electrical-Circuits_Electrical-Circuits-Lab,
Digital-Logic-Lab,,Digital-Logic

下面是我的Python代码的一部分:

import pandas as pd

df = pd.read_csv('courses.csv', dtype=str)
df.fillna('', inplace=True)

df['finished'] = False

finished_courses = ['Calculus-A', 'Calculus-B', 'Linear-Algebra', 'Physics-A', 'Physics-A-Lab', 'Physics-B',
                    'Physics-B-Lab']

for finished_course in finished_courses:
    df.loc[df['course_name'] == finished_course, 'finished'] = True

df['pre_requisites'] = df['pre_requisites'].apply(lambda pre_requisites: pre_requisites.split('_'))

courses_without_pre_requisites = df[df['pre_requisites'].apply(lambda pre_requisites: pre_requisites == [''])]
courses_without_pre_requisites_without_co_requisites = courses_without_pre_requisites[
    courses_without_pre_requisites['co_requisite'].apply(lambda co_requisites: co_requisites == '')]
courses_without_pre_requisites_with_co_requisites = courses_without_pre_requisites[
    courses_without_pre_requisites['co_requisite'].apply(lambda co_requisites: co_requisites != '')]
courses_with_pre_requisites = df[df['pre_requisites'].apply(lambda pre_requisites: pre_requisites != [''])]
courses_with_pre_requisites_with_co_requisites = courses_with_pre_requisites[
    courses_with_pre_requisites['co_requisite'].apply(lambda co_requisites: co_requisites != '')]
courses_with_pre_requisites_without_co_requisites = courses_with_pre_requisites[
    courses_with_pre_requisites['co_requisite'].apply(lambda co_requisites: co_requisites == '')]
courses_with_finished_pre_requisites = courses_with_pre_requisites_without_co_requisites[
    courses_with_pre_requisites_without_co_requisites['pre_requisites'].apply(
        lambda pre_requisite: set(pre_requisite).issubset(set(df[df['finished']]['course_name'])))]

courses_to_be_registered = pd.concat(
    [courses_without_pre_requisites_without_co_requisites, courses_with_finished_pre_requisites])
courses_to_be_registered = courses_to_be_registered[~(courses_to_be_registered['finished'])]

print('Courses to be registered:')
print(courses_to_be_registered['course_name'])

下面是输出:

Courses to be registered:
Calculus-C
Computer-Programming

以下是所需的输出:

Calculus-C
Differential-Equations
Computer-Programming
Electrical-Circuits
Electrical-Circuits-Lab
f87krz0w

f87krz0w1#

如果我理解正确的话,你可以使用递归来完成这个任务:

def check_apply(course):
    def _can_be_applied(c):
        if not c["pre_requisites"] and not c["co_requisite"]:
            return True
        elif not c["pre_requisites"] and c["co_requisite"]:
            return _can_be_applied(df.loc[c["co_requisite"]])
        else:
            return all(v in finished_courses for v in c["pre_requisites"])

    return _can_be_applied(course)

# load the CSV, change NaNs to empty lists and ""
df = pd.read_csv("your_data.csv")
df["pre_requisites"] = df["pre_requisites"].apply(
    lambda x: x.split("_") if pd.notna(x) else []
)
df["co_requisite"] = df["co_requisite"].fillna("")

finished_courses = {
    "Calculus-A",
    "Calculus-B",
    "Linear-Algebra",
    "Physics-A",
    "Physics-A-Lab",
    "Physics-B",
    "Physics-B-Lab",
}

mask = ~df["course_name"].isin(finished_courses).values
df = df.set_index("course_name")

df.loc[mask, "can_apply"] = df[mask].apply(check_apply, axis=1)
print(df)

创建can_apply列,其中True表示用户可以申请的课程:

pre_requisites            co_requisite can_apply
course_name                                                                                                                    
Calculus-A                                                                                 []                               NaN
Calculus-B                                                                       [Calculus-A]                               NaN
Linear-Algebra                                                                             []                               NaN
Calculus-C                                                       [Calculus-B, Linear-Algebra]                              True
Differential-Equations                                                       [Linear-Algebra]              Calculus-C      True
Computer-Programming                                             [Calculus-A, Linear-Algebra]                              True
Physics-A                                                                                  []              Calculus-A       NaN
Physics-A-Lab                                                                              []               Physics-A       NaN
Physics-B                                                                         [Physics-A]                               NaN
Physics-B-Lab                                                                 [Physics-A-Lab]               Physics-B       NaN
Electrical-Circuits                                                               [Physics-B]  Differential-Equations      True
Electrical-Circuits-Lab                                                       [Physics-B-Lab]     Electrical-Circuits      True
Digital-Logic            [Computer-Programming, Electrical-Circuits, Electrical-Circuits-Lab]                             False
Digital-Logic-Lab                                                                          []           Digital-Logic     False

相关问题