Rename choice -> scheme

M main.hs => main.hs +12 -12

@@ 1,15 1,15 @@import qualified Data.List as List import qualified Control.Monad as Monad printTimetable choice = do printTimetable scheme = do putStrLn "" putStrLn $ List.intercalate ", " [course ++ "S" ++ sec | (course, (sec, _)) <- choice] putStrLn $ List.intercalate ", " [course ++ "S" ++ sec | (course, (sec, _)) <- scheme] putStrLn "M\tTu\tW\tTh\tF" putStr table where table = unlines samePeriodOfDay samePeriodOfDay = map (List.intercalate "\t" . horizontal) allPeriodsOfDay where table = unlines periodsOfDay periodsOfDay = map (List.intercalate "\t" . horizontal) allPeriodsOfDay horizontal pod = map (courseInSlot pod) allDaysOfWeek courseInSlot pod dow = foldl (foldFunc pod dow) "" choice courseInSlot pod dow = foldl (foldFunc pod dow) "" scheme foldFunc pod dow acc x = if (dow ++ " " ++ pod) `elem` (snd $ snd x) then fst x else acc where periodString = dow ++ " " ++ pod@@ 22,16 22,16 @@ printTimetable choice = doconflict :: (Eq a) => ([a], [a]) -> Bool conflict courses = not $ null $ List.intersect (fst courses) (snd courses) -- all possible choices; cartesian product of all courses and all sections thereof sectionChoices :: [(a, [(b, [c])])] -> [[(a, (b, [c]))]] sectionChoices [crs] = [[(fst crs, secs)] | secs <- snd crs] sectionChoices (crs : courses) = -- all possible schemes; cartesian product of all courses and all sections thereof sectionSchemes :: [(a, [(b, [c])])] -> [[(a, (b, [c]))]] sectionSchemes [crs] = [[(fst crs, secs)] | secs <- snd crs] sectionSchemes (crs : courses) = [(fst crs, secs) : known | secs <- snd crs, known <- known_courses] where known_courses = sectionChoices courses where known_courses = sectionSchemes courses -- only keep choices that do not conflict -- only keep schemes that do not conflict resolve :: (Ord a, Ord b, Ord c, Eq c) => [(a, [(b, [c])])] -> [[(a, (b, [c]))]] resolve courses = filter noConflict (sectionChoices courses) resolve courses = filter noConflict (sectionSchemes courses) where noConflict secs = all (== False) $ map conflict $ comb2 secs comb2 secs = [(snd $ snd s1, snd $ snd s2) | s1 <- secs, s2 <- secs, s1 < s2]

M main.py => main.py +29 -26

@@ 1,38 1,41 @@#!/usr/bin/python from itertools import combinations # dow, pod for short DAYS_OF_WEEK = ["M", "Tu", "W", "Th", "F"] PERIODS = ["08", "10", "12", "14", "16", "18"] PERIODS_OF_DAY = ["08", "10", "12", "14", "16", "18"] def parse_period(period: str) -> tuple: dow, prd = period.split(" ") return (DAYS_OF_WEEK.index(dow), PERIODS.index(prd)) dow, pod = period.split(" ") return (DAYS_OF_WEEK.index(dow), PERIODS_OF_DAY.index(pod)) def print_timetable(courses: dict, choice: list): # the design of this program allows only one course per period # period-major order because one period == one row when printed timetable = [["" for dow in DAYS_OF_WEEK] for prd in PERIODS] for course, sec in choice: def print_timetable(courses: dict, scheme: list): # this program is designed to allow only one course per period # period-major order because one period of day == one row when printed timetable = [["" for _ in DAYS_OF_WEEK] for _ in PERIODS_OF_DAY] for course, sec in scheme: periods = courses[course]["sections"][sec] for period in periods: dow, prd = parse_period(period) timetable[prd][dow] = f"{course}" dow, pod = parse_period(period) timetable[pod][dow] = course print(", ".join([f"{course}S{sec}" for course, sec in choice])) # print table header print(", ".join([f"{course}S{sec}" for course, sec in scheme])) print("\t".join(DAYS_OF_WEEK)) for periods in timetable: print("\t".join(periods)) # print timetable for courses_in_pod in timetable: print("\t".join(courses_in_pod)) def conflict(section1: list, section2: list): def conflict(section1: list, section2: list) -> bool: # check if two sections use the same period # section[12]: list of strings representing periods # section{1,2}: list of strings representing periods return any([(period in section1) for period in section2]) def section_choices(courses: dict): def section_schemes(courses: dict) -> list: if not courses: return []@@ 45,28 48,28 @@ def section_choices(courses: dict):return [[(course_name, sec_name)] for sec_name in course["sections"]] else: # inductive case # recurse with all courses but one, then branch out each # known choice with sections of said course known_choices = section_choices(courses) choices = [] for known in known_choices: # recurse with all courses but the one we removed, then branch out # each known scheme with all sections of said course known_schemes = section_schemes(courses) schemes = [] for known in known_schemes: for sec_name in course["sections"]: choices.append(known + [(course_name, sec_name)]) return choices schemes.append(known + [(course_name, sec_name)]) return schemes def resolve(courses: dict): for choice in section_choices(courses.copy()): for scheme in section_schemes(courses.copy()): if not any( [ conflict( courses[course1[0]]["sections"][course1[1]], courses[course2[0]]["sections"][course2[1]], ) for course1, course2 in combinations(choice, 2) for course1, course2 in combinations(scheme, 2) ] ): print_timetable(courses, choice) print_timetable(courses, scheme) print()