计算多个课表在一天早上、下午、晚上同样有课的周次

开学了,好奇和舍友分流后在早上下午晚上里同样要上课的周次区间,因此写下这个程序。

感觉就是合并区间 + 线性DP + 递归,还好我学过一点点算法。

比如,我要计算三个专业的课表在一周内的某天,例如星期一(星期几都好,反正这里计算的就是一天早中晚)有没有同样要在早上上课的周次,我就逐个把三个课表在这一天的早上的课程的一大段文字直接复制进去,程序会用正则表达式自动提取出单周双周或者不分单双周的时间。

注意,程序的输入和输出的周次区间都是闭区间。

# Coder: Keyal
# -*- coding: UTF-8 -*-
# Created on 2023/9/1-19:30
import re


def merge_all(three_lists):
    def merge(section):
        section = list(set(section))
        section.sort()
        section = list(map(list, section))
        i = 1
        while i < len(section):
            left_idx = i - 1
            right_idx = i
            if section[left_idx][1] >= section[right_idx][0] - 1:
                right_val = max(section[left_idx][1], section[right_idx][1])
                section[left_idx][1] = right_val
                section.pop(right_idx)
            else:
                i += 1

        return section

    def get_overlap(li):
        li = map(tuple, li)
        li = list(set(li))
        li.sort()

        res = []
        i = 1
        while i < len(li):
            left_idx = i - 1
            right_idx = i
            left_val = li[left_idx][1]
            right_val = li[right_idx][0]
            if left_val >= right_val:
                res.append([right_val, left_val])
            i += 1

        return res

    total = []
    for li in three_lists:
        merged_li = merge(li)
        total.append(merged_li)

    del li
    ol = get_overlap(total[0] + total[1])
    for i in range(2, len(total)):
        ol = get_overlap(ol + total[i])

    return ol if ol else '啥也没有'


def all_li_to_int(li, i):
    for j in range(i, len(li)):
        if isinstance(li[j], list):
            all_li_to_int(li[j], 0)
        else:
            li[j] = int(li[j])



def get_week_section_from_text(time_section):
    table_names = input("请输入课表列(按空格符分割):").split()
    tables = [list() for _ in range(len(table_names))]
    for i, n in enumerate(table_names, 1):
        state = ''
        print(f'开始接收-|-{n}-|-的-|-{time_section}-|-课表周次安排\n')
        while state := input(f"输入EOF以停止\n\n请输入--{n}--的--{time_section}--的所有课程周段(直接复制粘贴整段文字)\n:"):
            if 'EOF' in state:
                break
            week = re.findall(r'(\d*)-(\d*)周', state)
            print('获取到区间:\n', *week, sep='  ')
            odd_week = re.findall(r'(\d*)-(\d*)周\(单\)', state)
            even_week = re.findall(r'(\d*)-(\d*)周\(双\)', state)
            week = list(map(list, week))
            odd_week = list(map(list, odd_week))
            even_week = list(map(list, even_week))

            pcd_odd = []
            pcd_even = []
            week = list(map(tuple, week))
            for wk in odd_week:
                for k in range(int(wk[0]), int(wk[1]) + 1):
                    if k % 2 == 1:
                        pcd_odd.append((k, k,))
                        print(f'获取到  {k}周')
                print()
            for wk in even_week:
                for k in range(int(wk[0]), int(wk[1]) + 1):
                    if k % 2 == 0:
                        pcd_even.append((k, k,))
                        print(f'获取到  {k}周', end='  ')
                print()

            all_li_to_int(odd_week, 0)
            all_li_to_int(even_week, 0)
            all_li_to_int(week, 0)

            tables[i - 1].extend(week)
            tables[i - 1].extend(pcd_even)
            tables[i - 1].extend(pcd_odd)

    return tables


def main():
    while t := input("请输入你的时间段(早上、下午、晚上)"):
        print(f'现在开始计算{t}的重叠周次')

        tables = get_week_section_from_text(t)

        res = merge_all(tables)
        print(f'\n\n{t !s :-^15}的重叠周为{res !s :-^15}\n\n')


main()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值