Алгоритм для составления школьного расписания

Вообщем, составляю расписание на питоне. Данные гружу из файлов, структура примерно такая:

Класс (5, 6, 7 и тд):
  Список {урок - кол-во часов в неделю}:
    Русский язык: 3
    Математика: 4 и тд.

Учитель:
  Список: {урок - у каких классов ведет}
    Русский язык: (5, 6)
    Математика: (8, 11)

Нужно составить расписание на 5 дней, с кол-вом уроков в сумме совпадающих по часам их исходного файла.

При этом, нужно также соблюдать несколько условий:

Такой-то учитель не работает во вторник (пример)

У такого-то учителя в пятницу уроки только с 4 ставить

А также некоторые уроки в классах должны быть принудительно совмещены, не важно когда, важно совмещены.

Физкультура - (9, 11)

Я попробовал создавать расписание обычным циклом, структура расписания примерно такая:

class Week:
    days: list[Day]

class Day: 
    schedule: dict[Class, list[Lesson]

class Lesson:
    teacher: Teacher
    _class: Class
    subject: str

Так вот я проходился по очереди по каждому классу каждый день:

первый урок в понедельник пятый класс, первый урок в понедельник шестой класс, ...

первый урок во вторник пятый класс...

Чтобы таблица заполнялась более менее равномерно.

Исключения, вроде 'Учителя в такой то день не ставить' я еще кое как сделал, но когда сказали про принудительные совмещения, я выпал

Мне нужна идея, совет, без понятия вообще как это можно сделать

+ Код:

def create_shedule():
    for day in shedule.days:
        for sclass in classes:
            day.shedule[sclass] = []
    for i in range(1, 12):
        for day in shedule.days:
            for sclass in classes:
                if not sclass in day.shedule.keys():
                    day.shedule[sclass] = []
                choose_subject(sclass, day, i)



def choose_subject(sclass: Class, day: Day, lesson_num: int):

    if day.name == "Понедельник" and lesson_num == 1:
        add_lesson(Lesson(Teacher('Кл. руководитель'), sclass, 'Разговор о важном'), day)
        return
    
    a_subjects: list[str] = []
    
    
    for subject, hours in sclass.subjects.items():
        if hours > 0:
            a_subjects.append(subject)
    
    
            
    # Получает уроки которые сейчас
    now_lessons: list[Lesson] = []
    for _sclass, _lessons in day.shedule.items():
        if sclass.number != _sclass.number:
            if lesson_num <= len(_lessons):
                now_lessons.append(_lessons[lesson_num-1])
    
    
    # Выбираем уроки учителей, которые не заняты
    a_teachers: list[Teacher] = []       
    for teacher in teachers:
        take = True
        for lesson in now_lessons:
            if teacher.name == lesson.teacher.name:
                take = False
                break
        if take:
            a_teachers.append(teacher)
    
    if day.name == "Понедельник" and sclass.number == 7 and lesson_num == 1:
        print('eere')
        print(*a_teachers)
    
    if day.name == "Вторник":
        for teacher in a_teachers:
            if teacher.name == "К - конфеденциальность":
                a_teachers.remove(teacher)
                break
    
    if (day.name == "Вторник" or day.name == "Четверг") and lesson_num <= 4:
        for teacher in a_teachers:
            if teacher.name == "К - конфеденциальность":
                a_teachers.remove(teacher)
                break
            
    if day.name == "Пятница" and lesson_num == 4:
        for teacher in a_teachers:
            if teacher.name == "К - конфеденциальность":
                a_teachers.remove(teacher)
                break
    
    
    # Выбираем уроки, которые есть у доступных учителей
    r_subjects: list[str] = []
    for subject in a_subjects:
        for teacher in a_teachers:
            for _subject, c in teacher.subjects.items():
                if sclass.number in c:
                    if subject == _subject:
                        r_subjects.append(subject)

    # Выбираем уроки которые еще не были
    wn_subjects: list[str] = []
    tmp: list[str] = []
    for _sclass, lessons in day.shedule.items():
        if _sclass.number == sclass.number:
            for lesson in lessons:
                tmp.append(lesson.subject)
            break    
    for subject in r_subjects:
        if subject not in tmp:
            wn_subjects.append(subject) 
    
    teach, subj = Teacher('err'), 'None'
    # Окончательный выбор урока
    if len(wn_subjects) > 0:
        if rnd:
            subject = random.choice(wn_subjects)
        else:
            subject = wn_subjects[0]
        for teacher in teachers:
            for tsubject in teacher.subjects.keys():
                if subject == tsubject:
                    if sclass.number in teacher.subjects[subject]:
                        teach = teacher
                        subj = subject
                        break
    else:
        if len(r_subjects) > 0:
            if rnd:
                subject = random.choice(r_subjects)
            else:
                subject = r_subjects[0]
            for teacher in teachers:
                for tsubject in teacher.subjects.keys():
                    if subject == tsubject:
                        if sclass.number in teacher.subjects[subject]:
                            teach = teacher
                            subj = subject
                            break
    
    if subj == "Старт в науку" and sclass.number == 7:
        set_lesson(Lesson(teach, classes[4], subj), day, lesson_num)
    
    if subj == "Практикум по географии" and sclass.number == 8:
        set_lesson(Lesson(teach, classes[5], subj), day, lesson_num)
                    
    if subj == "Информатика" and sclass.number == 9:
        set_lesson(Lesson(teach, classes[5], subj), day, lesson_num) 
        
    if subj == "История" and sclass.number == 9:
        set_lesson(Lesson(teach, classes[5], subj), day, lesson_num) 
        
    if subj == "ОДКНР" and sclass.number == 5:
        set_lesson(Lesson(teach, classes[1], subj), day, lesson_num)               
    
    if subj == "Физическая культура" and sclass.number == 9:
        set_lesson(Lesson(teach, classes[5], subj), day, lesson_num) 
    
    if subj == "ОБЗР" and sclass.number == 9:
        print('Hello')
        set_lesson(Lesson(teach, classes[5], subj), day, lesson_num) 
                    
    if teach.name != 'err':
        add_lesson(Lesson(teach, sclass, subj), day)
        return
    
def add_lesson(lesson: Lesson, day: Day): 
    try:
        if lesson.sclass.subjects[lesson.subject] > 0:
            day.shedule[lesson.sclass].append(lesson)
            lesson.sclass.subjects[lesson.subject] -= 1
    except Exception as ex:
        pass

def set_lesson(lesson: Lesson, day: Day, lesson_num: int):
    try:
        if lesson.sclass.subjects[lesson.subject] > 0:
            day.shedule[lesson.sclass].insert(lesson_num-1, lesson)
            lesson.sclass.subjects[lesson.subject] -= 1
    except Exception as ex:
        pass

Просто прохожусь циклами, проверяю доступность уроков


Ответы (0 шт):