开学了,好奇和舍友分流后在早上下午晚上里同样要上课的周次区间,因此写下这个程序。
感觉就是合并区间 + 线性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()