[+] A2
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
\documentclass[fontsize=11pt]{article}
|
||||
\usepackage{amsmath}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[margin=0.75in]{geometry}
|
||||
|
||||
\title{CSC110 Fall 2021 Assignment 2: Logic, Constraints, and Nested Data}
|
||||
\author{TODO: FILL IN YOUR NAME HERE}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
||||
\section*{Part 1: Predicate Logic}
|
||||
|
||||
\begin{enumerate}
|
||||
|
||||
\item[1.]
|
||||
\begin{enumerate}
|
||||
\item[1.] TODO: Write your answer and justification here.
|
||||
\item[2.] TODO: Write your answer and justification here.
|
||||
\item[3.] TODO: Write your answer and justification here.
|
||||
\end{enumerate}
|
||||
|
||||
\item[2.]
|
||||
\begin{enumerate}
|
||||
\item[1.] TODO: Write your definition for $P(x)$ here.
|
||||
\item[2.] TODO: Write your definition for $Q(x)$ here.
|
||||
\end{enumerate}
|
||||
TODO: Briefly justify your response here.
|
||||
|
||||
\item[3.]
|
||||
Complete this part in the provided \texttt{a2\_part1.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\item[4.]
|
||||
Complete this part in the provided \texttt{a2\_part1.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
\section*{Part 2: Conditional Execution}
|
||||
|
||||
Complete this part in the provided \texttt{a2\_part2.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\newpage
|
||||
|
||||
\section*{Part 3: Generating a Timetable}
|
||||
|
||||
\begin{enumerate}
|
||||
|
||||
\item[1.]
|
||||
Complete this part in the provided \texttt{a2\_part3.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\item[2.]
|
||||
|
||||
\begin{enumerate}
|
||||
\item[(a)]
|
||||
|
||||
\emph{IMPORTANT DEFINITIONS/NOTATION} (don't change this text!)
|
||||
|
||||
We define the following sets:
|
||||
|
||||
\begin{itemize}
|
||||
\item $C$: the set of all possible courses
|
||||
\item $S$: the set of all possible sections
|
||||
\item $M$: the set of all possible meeting times
|
||||
\item $SC$: the set of all possible schedules
|
||||
\end{itemize}
|
||||
|
||||
We also define the following notation for expressions involving the elements of these sets:
|
||||
|
||||
\begin{itemize}
|
||||
\item
|
||||
The first three (courses/sections/meeting times) are represented as tuples (as described in the assignment handout), and you can use the indexing operation on these values. For example, you could translate ``every section term is in $\{'F', 'S', 'Y'\}$'' into predicate logic as the statement:
|
||||
|
||||
\[\forall s \in S,~ s[1] \in \{'F', 'S', 'Y' \} \]
|
||||
|
||||
\item
|
||||
The start and end times of a meeting time can be compared chronologically using the standard $<$, $\leq$, $>$, and $\geq$ operators.
|
||||
|
||||
\item
|
||||
For a section $s \in S$, $s[2]$ represents a tuple of meeting times.
|
||||
You may use standard set operations and quantifiers for these tuples (pretend they are sets).
|
||||
For example, we can say:
|
||||
|
||||
\begin{itemize}
|
||||
\item $\forall s \in S,~ s[2] \subseteq M$
|
||||
\item $\forall s \in S,~ \forall m \in s[2],~ m[1] < m[2]$
|
||||
\end{itemize}
|
||||
|
||||
\item
|
||||
Finally, for a schedule $sc \in SC$, you can use the notation $sc.sections$ to refer to a set of all sections in that schedule.
|
||||
You can use quantifiers with that set of schedules as well, e.g.
|
||||
$\forall s \in sc.sections,~ ...$
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Predicate for meeting times conflicting:}
|
||||
% TODO: fill in the predicate definition for two meeting times conflicting
|
||||
|
||||
\begin{align*}
|
||||
MeetingTimesConflict(m_1, m_2) : TODO
|
||||
\qquad \text{where $m_1, m_2 \in M$}
|
||||
\end{align*}
|
||||
|
||||
\smallskip
|
||||
|
||||
\textbf{Predicate for sections conflicting:}
|
||||
% TODO: fill in the predicate definition for two sections conflicting.
|
||||
% Use the MeetingTimesConflict predicate in your response.
|
||||
|
||||
\begin{align*}
|
||||
SectionsConflict(s_1, s_2) : TODO
|
||||
\qquad \text{where $s_1, s_2 \in S$}
|
||||
\end{align*}
|
||||
|
||||
\smallskip
|
||||
|
||||
\textbf{Predicate for valid schedule:}
|
||||
% TODO: fill in the predicate definition for a schedule being valid.
|
||||
% Use the SectionsConflict predicate in your response.
|
||||
|
||||
\begin{align*}
|
||||
IsValidSchedule(sc) : TODO
|
||||
\qquad \text{where $sc \in SC$}
|
||||
\end{align*}
|
||||
|
||||
|
||||
\item[(b)]
|
||||
Complete this part in the provided \texttt{a2\_part3.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
\end{enumerate}
|
||||
|
||||
\item[3.]
|
||||
|
||||
\begin{enumerate}
|
||||
\item[(a)]
|
||||
|
||||
You may use all notation from question 2(a).
|
||||
Note that a course $c \in C$ is a tuple, and $c[2]$ is a set of sections, and so can be quantified over: $\forall s \in c[2], ...$.
|
||||
|
||||
\smallskip
|
||||
|
||||
\textbf{Predicate for section-schedule compatibility:}
|
||||
% TODO: fill in the predicate definition for a section being compatible with a schedule.
|
||||
|
||||
\begin{align*}
|
||||
IsCompatibleSection(sc, s) : TODO
|
||||
\qquad \text{where $sc \in SC, s \in S$}
|
||||
\end{align*}
|
||||
|
||||
\smallskip
|
||||
|
||||
\textbf{Predicate for course-schedule compatibility:}
|
||||
% TODO: fill in the predicate definition for a course being compatible with a schedule.
|
||||
% Use IsCompatibleSection in your response.
|
||||
|
||||
\begin{align*}
|
||||
IsCompatibleCourse(sc, c) : TODO
|
||||
\qquad \text{where $sc \in SC, c \in C$}
|
||||
\end{align*}
|
||||
|
||||
\item[(b)]
|
||||
Complete this part in the provided \texttt{a2\_part3.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
\end{enumerate}
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
\section*{Part 4: Processing Raw Data}
|
||||
Complete this part in the provided \texttt{a2\_part4.py} starter file.
|
||||
Do \textbf{not} include your solution in this file.
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,323 @@
|
||||
"""CSC110 Fall 2021 Assignment 2, Part 3: Programming Tests
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
This Python module contains example tests you can run for Part 3 of this assignment. Please note
|
||||
that passing all these tests does NOT mean you have a 100% correct solution.
|
||||
|
||||
Some of the tests are empty, consider completing them. Also consider adding more of your own tests.
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu, Mario Badr, and Tom Fairgrieve.
|
||||
"""
|
||||
import pytest
|
||||
import datetime
|
||||
|
||||
import a2_part3 as a2_courses
|
||||
import a2_part4
|
||||
|
||||
###################################################################################################
|
||||
# Sample Meeting Times
|
||||
###################################################################################################
|
||||
MON_9_TO_11 = ('Monday', datetime.time(9), datetime.time(11))
|
||||
MON_12_TO_1 = ('Monday', datetime.time(12), datetime.time(13))
|
||||
|
||||
TUE_9_TO_11 = ('Tuesday', datetime.time(9), datetime.time(11))
|
||||
TUE_10_TO_12 = ('Tuesday', datetime.time(10), datetime.time(12))
|
||||
|
||||
WED_9_TO_11 = ('Wednesday', datetime.time(9), datetime.time(11))
|
||||
WED_12_TO_1 = ('Wednesday', datetime.time(12), datetime.time(13))
|
||||
|
||||
THU_3_TO_4 = ('Thursday', datetime.time(15), datetime.time(16))
|
||||
THU_1_TO_2_30 = ('Thursday', datetime.time(13), datetime.time(14, 30))
|
||||
|
||||
FRI_9_TO_11 = ('Friday', datetime.time(9), datetime.time(11))
|
||||
FRI_12_TO_1 = ('Friday', datetime.time(12), datetime.time(13))
|
||||
FRI_1_TO_2 = ('Friday', datetime.time(13), datetime.time(14))
|
||||
|
||||
###################################################################################################
|
||||
# Sample Sections
|
||||
###################################################################################################
|
||||
MAT137_LEC0101 = ('LEC0101', 'Y', (MON_9_TO_11, TUE_9_TO_11, WED_9_TO_11))
|
||||
MAT137_LEC0201 = ('LEC0201', 'Y', (MON_12_TO_1, WED_12_TO_1, FRI_12_TO_1))
|
||||
|
||||
CSC110_LEC0101 = ('LEC0101', 'F', (MON_9_TO_11, TUE_9_TO_11, WED_9_TO_11))
|
||||
CSC111_LEC0301 = ('LEC0301', 'S', (MON_9_TO_11, TUE_9_TO_11, FRI_1_TO_2))
|
||||
|
||||
CON123_LEC0123 = ('LEC0123', 'F', (FRI_1_TO_2,))
|
||||
CON123_LEC0321 = ('LEC0321', 'S', (TUE_10_TO_12, FRI_1_TO_2))
|
||||
|
||||
CON333_LEC1337 = ('LEC1337', 'F', (WED_9_TO_11,))
|
||||
CON333_LEC2001 = ('LEC2001', 'F', (MON_9_TO_11,))
|
||||
|
||||
STA130_LEC0101 = ('LEC0101', 'F', (THU_3_TO_4,))
|
||||
STA130_LEC0201 = ('LEC0201', 'F', (THU_1_TO_2_30,))
|
||||
|
||||
###################################################################################################
|
||||
# Sample Courses
|
||||
###################################################################################################
|
||||
CSC110 = ('CSC110', 'Foundations of Computer Science I', {CSC110_LEC0101})
|
||||
CSC111 = ('CSC111', 'Foundations of Computer Science II', {CSC111_LEC0301})
|
||||
|
||||
CON123 = ('CON123', 'Foundation Construction', {CON123_LEC0123, CON123_LEC0321})
|
||||
CON333 = ('CON333', 'Advanced Brick Laying', {CON333_LEC1337, CON333_LEC2001})
|
||||
|
||||
MAT137 = ('MAT137', 'Calculus!', {MAT137_LEC0101, MAT137_LEC0201})
|
||||
|
||||
STA130 = ('STA130', 'Introduction to Statistical Reasoning',
|
||||
{STA130_LEC0101, STA130_LEC0201})
|
||||
|
||||
###################################################################################################
|
||||
# Sample Schedule
|
||||
###################################################################################################
|
||||
SCHEDULE_1 = {
|
||||
'CSC110': CSC110_LEC0101,
|
||||
'CSC111': CSC111_LEC0301
|
||||
}
|
||||
|
||||
SCHEDULE_2 = {
|
||||
'CON123': CON123_LEC0123,
|
||||
'CSC111': CSC111_LEC0301,
|
||||
'CON333': CON333_LEC1337
|
||||
}
|
||||
|
||||
SCHEDULE_3 = {
|
||||
'CSC110': CSC110_LEC0101,
|
||||
'CSC111': CSC111_LEC0301,
|
||||
'MAT137': MAT137_LEC0201,
|
||||
'CON123': CON123_LEC0321
|
||||
}
|
||||
|
||||
# Note that this is SCHEDULE_1 but with CON123 added
|
||||
SCHEDULE_4 = {
|
||||
'CSC110': CSC110_LEC0101,
|
||||
'CSC111': CSC111_LEC0301,
|
||||
'CON123': CON123_LEC0123
|
||||
}
|
||||
|
||||
###################################################################################################
|
||||
# Sample Raw Data
|
||||
###################################################################################################
|
||||
WED_9_TO_11_RAW = {'day': 'Wednesday', 'startTime': '09:00', 'endTime': '11:00'}
|
||||
MON_9_TO_11_RAW = {'day': 'Monday', 'startTime': '09:00', 'endTime': '11:00'}
|
||||
CON333_LEC1337_RAW = {'sectionCode': 'LEC1337', 'term': 'F', 'meetingTimes': [WED_9_TO_11_RAW]}
|
||||
CON333_LEC2001_RAW = {'sectionCode': 'LEC2001', 'term': 'F', 'meetingTimes': [MON_9_TO_11_RAW]}
|
||||
CON333_RAW = {'courseCode': 'CON333', 'courseTitle': 'Advanced Brick Laying',
|
||||
'sections': [CON333_LEC1337_RAW, CON333_LEC2001_RAW]}
|
||||
|
||||
|
||||
###################################################################################################
|
||||
# Part 3 Question 1
|
||||
###################################################################################################
|
||||
def test_num_sections() -> None:
|
||||
"""
|
||||
Test num_sections with 1 section from CSC110
|
||||
"""
|
||||
assert a2_courses.num_sections(CSC110) == 1
|
||||
|
||||
|
||||
def test_num_lecture_hours() -> None:
|
||||
"""
|
||||
Test num_lecture_hours with MAT137
|
||||
"""
|
||||
assert a2_courses.num_lecture_hours(MAT137_LEC0101) == 6
|
||||
|
||||
|
||||
# TODO: Create more tests
|
||||
|
||||
###################################################################################################
|
||||
# Part 3 Question 2
|
||||
###################################################################################################
|
||||
def test_times_conflict() -> None:
|
||||
"""
|
||||
Test times_conflict with conflicting meetings times that overlap
|
||||
"""
|
||||
m1 = TUE_9_TO_11
|
||||
m2 = TUE_10_TO_12
|
||||
expected = True
|
||||
actual = a2_courses.times_conflict(m1, m2)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_times_no_conflict() -> None:
|
||||
"""
|
||||
Test times_conflict with non-conflicting meetings times
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_sections_conflict() -> None:
|
||||
"""
|
||||
Test sections_conflict with conflicting sections
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_sections_no_conflict() -> None:
|
||||
"""
|
||||
Test sections_conflict with non-conflicting sections
|
||||
"""
|
||||
s1 = CON123_LEC0123
|
||||
s2 = CON123_LEC0321
|
||||
expected = False
|
||||
actual = a2_courses.sections_conflict(s1, s2)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_is_valid() -> None:
|
||||
"""
|
||||
Test is_valid with valid schedule
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_not_valid() -> None:
|
||||
"""
|
||||
Test is_valid with invalid schedule
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_2_possible_schedule_combinations() -> None:
|
||||
"""
|
||||
Test possible_schedule_combinations with 2 possible combinations
|
||||
"""
|
||||
c1 = MAT137
|
||||
c2 = CSC111
|
||||
expected = 2
|
||||
actual = a2_courses.possible_schedules(c1, c2)
|
||||
assert len(actual) == expected
|
||||
|
||||
|
||||
def test_4_possible_schedule_combinations() -> None:
|
||||
"""
|
||||
Test possible_schedule_combinations with 4 possible combinations
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_1_valid_schedule_combinations() -> None:
|
||||
"""
|
||||
Test valid_schedule_combinations with valid schedule combination, bounds of 1
|
||||
"""
|
||||
c1 = MAT137
|
||||
c2 = CSC111
|
||||
expected = 1
|
||||
actual = a2_courses.valid_schedules(c1, c2)
|
||||
assert len(actual) == expected
|
||||
|
||||
|
||||
def test_4_valid_schedule_combinations() -> None:
|
||||
"""
|
||||
Test valid_schedule_combinations with 4 valid schedule combinations
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_possible_five_course_schedules() -> None:
|
||||
"""
|
||||
Test possible_five_course_schedules with five possible course schedules
|
||||
"""
|
||||
c1 = CSC110
|
||||
c2 = CSC111
|
||||
c3 = CON123
|
||||
c4 = CON333
|
||||
c5 = MAT137
|
||||
expected = 8
|
||||
actual = a2_courses.possible_five_course_schedules(c1, c2, c3, c4, c5)
|
||||
assert len(actual) == expected
|
||||
|
||||
|
||||
def test_invalid_five_course_schedules() -> None:
|
||||
"""
|
||||
Test valid_five_course_schedules with invalid five course schedule
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
# TODO: Create more tests
|
||||
|
||||
###################################################################################################
|
||||
# Part 3 Question 3
|
||||
###################################################################################################
|
||||
def test_section_compatible() -> None:
|
||||
"""
|
||||
Test is_section_compatible with compatible sections
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_section_not_compatible() -> None:
|
||||
"""
|
||||
Test is_section_compatible with incompatible sections
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_course_compatible() -> None:
|
||||
"""
|
||||
Test is_course_compatible with compatible course
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_course_not_compatible() -> None:
|
||||
"""
|
||||
Test is_course_compatible with incompatible course
|
||||
"""
|
||||
# TODO: Create a test
|
||||
|
||||
|
||||
def test_compatible_sections() -> None:
|
||||
"""
|
||||
Test compatible_sections with compatible sections
|
||||
"""
|
||||
actual = a2_courses.compatible_sections(SCHEDULE_1, CON123) == {CON123_LEC0123}
|
||||
expected = True
|
||||
assert actual == expected
|
||||
|
||||
|
||||
# TODO: Create more tests
|
||||
|
||||
###################################################################################################
|
||||
# Part 4
|
||||
###################################################################################################
|
||||
def test_transform_course_data() -> None:
|
||||
"""
|
||||
Test transform_course_data
|
||||
"""
|
||||
expected = CON333
|
||||
actual = a2_part4.transform_course_data(CON333_RAW)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_transform_section_data() -> None:
|
||||
"""
|
||||
Test transform_section_data
|
||||
"""
|
||||
expected = CON333_LEC2001
|
||||
actual = a2_part4.transform_section_data(CON333_LEC2001_RAW)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_transform_meeting_time_data() -> None:
|
||||
"""
|
||||
Test transform_meeting_time_data
|
||||
"""
|
||||
expected = MON_9_TO_11
|
||||
actual = a2_part4.transform_meeting_time_data(MON_9_TO_11_RAW)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
# TODO: Create more tests
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main(['a2_example_tests.py'])
|
||||
@@ -0,0 +1,91 @@
|
||||
"""CSC110 Fall 2021 Assignment 2, Part 1: Predicate Logic
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
This Python module contains the functions you should complete for Part 1, Questions 3 and 4.
|
||||
Your task is to:
|
||||
|
||||
1. Implement functions `statement3` and `statement4` so that they translate the statements given in
|
||||
Part 1.
|
||||
2. Define predicate functions `example_p`, and `example_q` as an example arguments to `statement3`
|
||||
and `statement4`, then use `test_statements_different` to show that these two functions don't
|
||||
compute the same things.
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu and Mario Badr and Tom Fairgrieve.
|
||||
"""
|
||||
from typing import Callable
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Part 1, Question 3
|
||||
###############################################################################
|
||||
def statement3(my_set: set[int],
|
||||
my_p: Callable[[int], bool],
|
||||
my_q: Callable[[int], bool]) -> bool:
|
||||
"""Implementation of Statement 3 from Part 1, Question 2.
|
||||
|
||||
This statement is represented as a function that takes three arguments:
|
||||
- a set my_set (corresponds to "S" from the statement)
|
||||
- a predicate my_p (corresponds to the predicate "P" from the statement);
|
||||
its domain is my_set
|
||||
- a predicate my_q (corresponds to the predicate "Q" from the statement);
|
||||
its domain is my_set
|
||||
|
||||
Note that my_p is a *function* and can be called inside the body below, e.g. my_p(...).
|
||||
Similarly, my_q is also a function and can be called using my_q(...).
|
||||
|
||||
Preconditions:
|
||||
- my_p can be called on every element from my_set
|
||||
- my_q can be called on every element from my_set
|
||||
"""
|
||||
|
||||
|
||||
def statement4(my_set: set[int],
|
||||
my_p: Callable[[int], bool],
|
||||
my_q: Callable[[int], bool]) -> bool:
|
||||
"""Implementation of Statement 4 from Part 1, Question 2.
|
||||
"""
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Part 1, Question 4
|
||||
###############################################################################
|
||||
def test_statements_different() -> None:
|
||||
"""A test that verifies that statement3 and statement4 are not equivalent.
|
||||
"""
|
||||
my_set = set(range(0, 10))
|
||||
assert statement3(my_set, example_p, example_q) != statement4(my_set, example_p, example_q)
|
||||
|
||||
|
||||
def example_p(x: int) -> bool:
|
||||
"""An example predicate for "my_p" that can be used in test_statements_different.
|
||||
"""
|
||||
|
||||
|
||||
def example_q(x: int) -> bool:
|
||||
"""An example predicate for "my_q" that can be used in test_statements_different.
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import pytest
|
||||
pytest.main(['a2_part1.py', '-v'])
|
||||
|
||||
# When you are ready to check your work with python_ta, uncomment the following lines.
|
||||
# (Delete the "#" and space before each line.)
|
||||
# IMPORTANT: keep this code indented inside the "if __name__ == '__main__'" block
|
||||
# Leave this code uncommented when you submit your files.
|
||||
# import python_ta
|
||||
# python_ta.check_all(config={
|
||||
# 'max-line-length': 100,
|
||||
# 'disable': ['R1705', 'R1729']
|
||||
# })
|
||||
@@ -0,0 +1,101 @@
|
||||
"""CSC110 Fall 2021 Assignment 2, Part 2: Conditional Execution
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
|
||||
This Python module contains the functions you should complete for Part 2, Questions 1 and 2.
|
||||
Note that we've only given the headers for the functions that you should complete.
|
||||
To test your work against the original functions, we suggest:
|
||||
|
||||
1. Create a NEW Python file (not to be handed in) and copy and paste the original
|
||||
functions from the assignment handout into your new file.
|
||||
2. a) Run each file in the Python console and call the corresponding functions to
|
||||
see if their return values match.
|
||||
b) Write a few unit tests that check whether their return values match.
|
||||
c) Use hypothesis to create *property-based tests* to see whether their return
|
||||
values match on a wide range of inputs. (This is a perfect case when when
|
||||
to use property-based testing!!)
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu, Mario Badr, and Tom Fairgrieve.
|
||||
"""
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Part 2, Question 1
|
||||
###############################################################################
|
||||
def mystery_1a_flat(x: int, y: set[int]) -> str:
|
||||
"""Return the same value as mystery_1a_nested, but using just a single if statement."""
|
||||
if len(y) > 1 and x <= 0:
|
||||
return 'David'
|
||||
elif x > 1 and sum({n ** 2 for n in y}) >= 10:
|
||||
return 'Mario'
|
||||
else:
|
||||
return 'David'
|
||||
|
||||
|
||||
def mystery_1b_flat(n: int, rows_of_nums: list[list[int]]) -> int:
|
||||
"""Return the same value as mystery_1b_nested, but using just a single if statement."""
|
||||
len_in_range = len(rows_of_nums) > n > 0
|
||||
if len_in_range and n == 1:
|
||||
return 0
|
||||
elif len_in_range and n in rows_of_nums[n]:
|
||||
return sum(rows_of_nums[n]) + n
|
||||
elif len_in_range:
|
||||
return sum(rows_of_nums[0])
|
||||
elif len(rows_of_nums) > 20:
|
||||
return 20
|
||||
else:
|
||||
return n
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Part 2, Question 2
|
||||
###############################################################################
|
||||
def mystery_2a_no_if(x: int, y: int, z: set[int]) -> bool:
|
||||
"""Return the same value as mystery_2a_if, but without using any if statements."""
|
||||
# if x >= y:
|
||||
# return x in z
|
||||
# else:
|
||||
# return x not in z and y not in z
|
||||
return (x >= y and x in z) or (x < y and (x not in z and y not in z))
|
||||
|
||||
|
||||
def mystery_2b_no_if(n: int) -> bool:
|
||||
"""Return the same value as mystery_2b_if, but without using any if statements."""
|
||||
return (n % 2 == 0 and n % 3 == 1) or (n % 2 == 1 and ((n <= 4 and n < 0) or (n > 4 and n % 3 != 1)))
|
||||
|
||||
|
||||
def mystery_2c_no_if(c1: int, c2: int, c3: int) -> bool:
|
||||
"""Return the same value as mystery_2c_if, but without using any if statements."""
|
||||
return c1 != c2 and ((c1 > c2 and c3 > c2) or (c1 <= c2 < c3))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import python_ta
|
||||
import python_ta.contracts
|
||||
|
||||
python_ta.contracts.DEBUG_CONTRACTS = False
|
||||
python_ta.contracts.check_all_contracts()
|
||||
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
|
||||
# When you are ready to check your work with python_ta, uncomment the following lines.
|
||||
# (Delete the "#" and space before each line.)
|
||||
# IMPORTANT: keep this code indented inside the "if __name__ == '__main__'" block
|
||||
# Leave this code uncommented when you submit your files.
|
||||
python_ta.check_all(config={
|
||||
'extra-imports': ['python_ta.contracts'],
|
||||
'max-line-length': 100,
|
||||
'disable': ['R1705']
|
||||
})
|
||||
@@ -0,0 +1,121 @@
|
||||
from a2_part2_q1_q2 import mystery_1a_flat, mystery_1b_flat, mystery_2a_no_if, mystery_2b_no_if, mystery_2c_no_if
|
||||
from hyhelper import *
|
||||
|
||||
|
||||
def mystery_1a_nested(x: int, y: set[int]) -> str:
|
||||
"""Mystery 1a."""
|
||||
if len(y) > 1 and x <= 0:
|
||||
return 'David'
|
||||
else:
|
||||
if x > 1 and sum({n**2 for n in y}) >= 10:
|
||||
return 'Mario'
|
||||
else:
|
||||
return 'David'
|
||||
|
||||
|
||||
def mystery_1b_nested(n: int, rows_of_nums: list[list[int]]) -> int:
|
||||
"""Mystery 1b."""
|
||||
if len(rows_of_nums) > n > 0:
|
||||
if n == 1:
|
||||
return 0
|
||||
elif n in rows_of_nums[n]:
|
||||
return sum(rows_of_nums[n]) + n
|
||||
else:
|
||||
return sum(rows_of_nums[0])
|
||||
else:
|
||||
if len(rows_of_nums) > 20:
|
||||
return 20
|
||||
else:
|
||||
return n
|
||||
|
||||
|
||||
def mystery_2a_if(x: int, y: int, z: set[int]) -> bool:
|
||||
"""Mystery 2a."""
|
||||
if x >= y:
|
||||
if x in z:
|
||||
return True
|
||||
elif y not in z:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
if x in z:
|
||||
return False
|
||||
elif y not in z:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def mystery_2b_if(n: int) -> bool:
|
||||
"""Mystery 2b."""
|
||||
if n % 2 == 0:
|
||||
if n % 3 == 1:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
elif n <= 4:
|
||||
if n < 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
if n % 3 == 1:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def mystery_2c_if(c1: int, c2: int, c3: int) -> bool:
|
||||
"""Mystery 2c."""
|
||||
if c1 == c2:
|
||||
return False
|
||||
elif c1 > c2:
|
||||
if c3 <= c2:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
if c2 < c3:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tests = [
|
||||
(
|
||||
(mystery_1a_nested, mystery_1a_flat),
|
||||
((-1, {1, 2}), (2, {10}), (-1, {0}))
|
||||
),
|
||||
(
|
||||
(mystery_1b_nested, mystery_1b_flat),
|
||||
((1, [[1], [1]]), (2, [[-999], [1], [2, 3]]), (2, [[-999, 9999], [1], [3, 4]]),
|
||||
(-1, [[1]] * 21), (-1, []))
|
||||
),
|
||||
(
|
||||
(mystery_2a_if, mystery_2a_no_if),
|
||||
((4, 2, {4}), (4, 2, {3}), (4, 2, {2}), (2, 4, {2}), (2, 4, {3}), (2, 4, {4}))
|
||||
),
|
||||
(
|
||||
(mystery_2b_if, mystery_2b_no_if),
|
||||
((4,), (2,), (-1,), (3,), (7,), (5,))
|
||||
),
|
||||
(
|
||||
(mystery_2c_if, mystery_2c_no_if),
|
||||
((1, 1, 0), (2, 1, 1), (2, 1, 2), (1, 2, 3), (1, 2, 1))
|
||||
)
|
||||
]
|
||||
|
||||
for funcs, paramsList in tests:
|
||||
color(f'&6Running tests for: {funcs}')
|
||||
for params in paramsList:
|
||||
color(f'* Test case {params}')
|
||||
orig = funcs[0](*params)
|
||||
flat = funcs[1](*params)
|
||||
color(f' - Orig: &b{orig}')
|
||||
color(f' - Flat: &b{flat}')
|
||||
assert orig == flat
|
||||
color(f'&a Pass!')
|
||||
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
"""CSC110 Fall 2020 Assignment 2, Part 2: Conditional Execution
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
|
||||
This Python module contains your work for Part 2, Question 3. We have provided the functions
|
||||
from the handout already, and you must NOT change these. Below them, we've provided one
|
||||
sample (incomplete) unit test for each function. Your task is to complete these sample tests,
|
||||
and then use the same format to create new ones to cover every possible execution path through
|
||||
the three given functions.
|
||||
|
||||
You must use the provided structure for ALL unit tests. The only difference between your
|
||||
tests should be which function is called, the argument values, and the expected return value.
|
||||
|
||||
Do not use hypothesis or property-based testing here.
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu, Mario Badr, and Tom Fairgrieve.
|
||||
"""
|
||||
|
||||
|
||||
###############################################################################
|
||||
# The given functions (DO NOT CHANGE THESE)
|
||||
###############################################################################
|
||||
def mystery_3a(c1: str, c2: str, c3: str) -> int:
|
||||
"""Function for question 3a."""
|
||||
if c1 == c2 and c1 == c3:
|
||||
return 1
|
||||
elif c1 == c2 and c1 != c3:
|
||||
return 2
|
||||
elif c2 == c3:
|
||||
return 3
|
||||
elif c1 == c3:
|
||||
return 4
|
||||
else:
|
||||
return 5
|
||||
|
||||
|
||||
def mystery_3b(c1: int, c2: int, c3: int) -> int:
|
||||
"""Function for question 3b."""
|
||||
if c1 >= c2:
|
||||
if c2 >= c3:
|
||||
return 1
|
||||
else:
|
||||
return 2
|
||||
else:
|
||||
if c2 <= c3:
|
||||
return 3
|
||||
else:
|
||||
return 4
|
||||
|
||||
|
||||
def mystery_3c(c1: float, c2: float, c3: float) -> int:
|
||||
"""Function for question 3c."""
|
||||
if c1 > 0:
|
||||
if c2 % 3 == 0:
|
||||
if c3 % c2 == 0:
|
||||
return 1
|
||||
else:
|
||||
return 2
|
||||
else:
|
||||
if c3 % c2 == 0:
|
||||
return 3
|
||||
else:
|
||||
return 4
|
||||
else:
|
||||
if c1 * c2 > 0:
|
||||
return 5
|
||||
elif c2 * c3 > 0:
|
||||
return 6
|
||||
elif c3 < 0:
|
||||
return 7
|
||||
else:
|
||||
return 8
|
||||
|
||||
|
||||
###############################################################################
|
||||
# The unit tests (do your work here)
|
||||
###############################################################################
|
||||
def test_mystery_3a_1() -> None:
|
||||
"""Test mystery_3a for an expected return value of 1."""
|
||||
expected = 1
|
||||
actual = mystery_3a("", "", "")
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3a_2() -> None:
|
||||
"""Test mystery_3a for an expected return value of 2."""
|
||||
expected = 2
|
||||
actual = mystery_3a("", "", " ")
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3a_3() -> None:
|
||||
"""Test mystery_3a for an expected return value of 3."""
|
||||
expected = 3
|
||||
actual = mystery_3a(" ", "", "")
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3a_4() -> None:
|
||||
"""Test mystery_3a for an expected return value of 4."""
|
||||
expected = 4
|
||||
actual = mystery_3a("", " ", "")
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3a_5() -> None:
|
||||
"""Test mystery_3a for an expected return value of 5."""
|
||||
expected = 5
|
||||
actual = mystery_3a("", " ", " ")
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3b_1() -> None:
|
||||
"""Test mystery_3b for an expected return value of 1."""
|
||||
expected = 1
|
||||
actual = mystery_3b(0, 0, 0)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3b_2() -> None:
|
||||
"""Test mystery_3b for an expected return value of 2."""
|
||||
expected = 2
|
||||
actual = mystery_3b(0, 0, 1)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3b_3() -> None:
|
||||
"""Test mystery_3b for an expected return value of 3."""
|
||||
expected = 3
|
||||
actual = mystery_3b(-1, 0, 1)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3b_4() -> None:
|
||||
"""Test mystery_3b for an expected return value of 4."""
|
||||
expected = 4
|
||||
actual = mystery_3b(-1, 0, -1)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_1() -> None:
|
||||
"""Test mystery_3c for an expected return value of 1."""
|
||||
expected = 1
|
||||
actual = mystery_3c(1, 3, 3)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_2() -> None:
|
||||
"""Test mystery_3c for an expected return value of 2."""
|
||||
expected = 2
|
||||
actual = mystery_3c(1, 3, 1)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_3() -> None:
|
||||
"""Test mystery_3c for an expected return value of 3."""
|
||||
expected = 3
|
||||
actual = mystery_3c(1, 2, 2)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_4() -> None:
|
||||
"""Test mystery_3c for an expected return value of 4."""
|
||||
expected = 4
|
||||
actual = mystery_3c(1, 2, 1)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_5() -> None:
|
||||
"""Test mystery_3c for an expected return value of 5."""
|
||||
expected = 5
|
||||
actual = mystery_3c(-1, -1, 0)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_6() -> None:
|
||||
"""Test mystery_3c for an expected return value of 6."""
|
||||
expected = 6
|
||||
actual = mystery_3c(-1, 1, 1)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_7() -> None:
|
||||
"""Test mystery_3c for an expected return value of 7."""
|
||||
expected = 7
|
||||
actual = mystery_3c(-1, 1, -1)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_mystery_3c_8() -> None:
|
||||
"""Test mystery_3c for an expected return value of 8."""
|
||||
expected = 8
|
||||
actual = mystery_3c(0, 0, 0)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import python_ta
|
||||
import python_ta.contracts
|
||||
python_ta.contracts.DEBUG_CONTRACTS = False
|
||||
python_ta.contracts.check_all_contracts()
|
||||
|
||||
import pytest
|
||||
pytest.main(['a2_part2_q3.py', '-v'])
|
||||
|
||||
# When you are ready to check your work with python_ta, uncomment the following lines.
|
||||
# (Delete the "#" and space before each line.)
|
||||
# IMPORTANT: keep this code indented inside the "if __name__ == '__main__'" block
|
||||
# IMPORTANT: Leave this code uncommented when you submit your files.
|
||||
python_ta.check_all(config={
|
||||
'extra-imports': ['python_ta.contracts'],
|
||||
'max-line-length': 100,
|
||||
'disable': ['R1705']
|
||||
})
|
||||
@@ -0,0 +1,248 @@
|
||||
"""CSC110 Fall 2021 Assignment 2, Part 3: Generating a Timetable
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
This Python module contains the functions you should complete for Part 3 of this assignment.
|
||||
Your task is to complete the functions in this module, following the definitions given in
|
||||
the assignment handout.
|
||||
|
||||
You may find it useful to write helper functions to split up your code (we've provided
|
||||
some hints on places to do so below).
|
||||
|
||||
You may, but are not required to, write doctests for this part.
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu, Mario Badr, and Tom Fairgrieve.
|
||||
"""
|
||||
import datetime
|
||||
|
||||
|
||||
###################################################################################################
|
||||
# Part 3, Question 1
|
||||
###################################################################################################
|
||||
def num_sections(course: tuple[str, str, set]) -> int:
|
||||
"""Return the number of sections for the given course.
|
||||
|
||||
Preconditions:
|
||||
- The input matches the format for a course described by the assignment handout.
|
||||
"""
|
||||
|
||||
|
||||
def num_lecture_hours(section: tuple[str, str, tuple]) -> int:
|
||||
"""Return the total number of lecture hours per week.
|
||||
|
||||
Preconditions:
|
||||
- The input matches the format for a section described by the assignment handout.
|
||||
|
||||
Hint: you can use ".hour" to access the hour attribute of a datetime.time value.
|
||||
"""
|
||||
|
||||
|
||||
def sections_in_semester(schedule: dict[str, tuple[str, str, tuple]], semester: str) \
|
||||
-> set[tuple[str, str, tuple]]:
|
||||
"""Return the set of all sections in schedule that are taken in semester.
|
||||
|
||||
Courses that are taken in both semesters (i.e., 'Y') should always be included.
|
||||
|
||||
Preconditions:
|
||||
- The input matches the format for a schedule described by the assignment handout.
|
||||
- semester in {'F', 'S'}
|
||||
"""
|
||||
|
||||
|
||||
###################################################################################################
|
||||
# Part 3, Question 2b
|
||||
###################################################################################################
|
||||
def times_conflict(m1: tuple[str, datetime.time, datetime.time],
|
||||
m2: tuple[str, datetime.time, datetime.time]) -> bool:
|
||||
"""Return whether the meeting times m1 and m2 conflict.
|
||||
|
||||
Hint:
|
||||
- You can use comparison operators like < and == with datetime.time objects
|
||||
|
||||
Preconditions:
|
||||
- m1 and m2 match the format for a meeting described by the assignment handout.
|
||||
"""
|
||||
|
||||
|
||||
def sections_conflict(s1: tuple[str, str, tuple], s2: tuple[str, str, tuple]) \
|
||||
-> bool:
|
||||
"""Return whether the sections s1 and s2 conflict.
|
||||
|
||||
Hint:
|
||||
- Use times_conflict
|
||||
|
||||
Preconditions:
|
||||
- s1 and s2 match the format for a section described by the assignment handout.
|
||||
"""
|
||||
|
||||
|
||||
def is_valid(schedule: dict[str, tuple[str, str, tuple]]) -> bool:
|
||||
"""Return whether the given schedule is valid.
|
||||
|
||||
Hint:
|
||||
- Refer to the handout for a definition of a valid schedule
|
||||
|
||||
Preconditions:
|
||||
- schedule matches the format for a schedule described by the assignment handout.
|
||||
"""
|
||||
|
||||
|
||||
def possible_schedules(c1: tuple[str, str, set], c2: tuple[str, str, set]) \
|
||||
-> list[dict[str, tuple[str, str, tuple]]]:
|
||||
"""Return a list of all possible schedules of courses c1 and c2.
|
||||
|
||||
Each returned schedule should contain exactly two key-value pairs, one with the course
|
||||
code and a section of c1, and the other with the course code and a section of c2.
|
||||
|
||||
Invalid schedules are returned in this list.
|
||||
|
||||
If a given course has no sections, then return an empty list.
|
||||
(This will happen "automatically" if you use a comprehension with an empty collection!)
|
||||
|
||||
Preconditions:
|
||||
- c1 and c2 match the format for a course described by the assignment handout.
|
||||
- c1 != c2
|
||||
"""
|
||||
|
||||
|
||||
def valid_schedules(c1: tuple[str, str, set],
|
||||
c2: tuple[str, str, set]) \
|
||||
-> list[dict[str, tuple[str, str, tuple]]]:
|
||||
"""Return a list of all VALID schedules of courses c1 and c2.
|
||||
|
||||
Each returned schedule should contain exactly two key-value pairs, one with the course
|
||||
code and a section of c1, and the other with the course code and a section of c2.
|
||||
|
||||
Invalid schedules are NOT returned in this list.
|
||||
|
||||
Hint:
|
||||
- Use is_valid
|
||||
- Use possible_schedules
|
||||
|
||||
Preconditions:
|
||||
- c1 and c2 match the format for a course described by the assignment handout.
|
||||
- c1 != c2
|
||||
"""
|
||||
|
||||
|
||||
def possible_five_course_schedules(c1: tuple[str, str, set],
|
||||
c2: tuple[str, str, set],
|
||||
c3: tuple[str, str, set],
|
||||
c4: tuple[str, str, set],
|
||||
c5: tuple[str, str, set]) -> list[dict[str, tuple]]:
|
||||
"""Return a list of every possible schedule that contains all given courses.
|
||||
|
||||
This is analogous to possible_schedules, except now there are 5 courses instead of 2.
|
||||
|
||||
If a given course has no sections, then return an empty list.
|
||||
(This will happen "automatically" if you use a comprehension with an empty collection!)
|
||||
|
||||
Preconditions:
|
||||
- all given courses match the format for a course described by the assignment handout.
|
||||
- c1 != c2 and c1 != c3 and c1 != c4 and c1 != c5
|
||||
- c2 != c3 and c2 != c4 and c2 != c5
|
||||
- c3 != c4 and c3 != c5
|
||||
- c4 != c5
|
||||
|
||||
HINT: you'll want a comprehension with 5 different variables. You can split up each
|
||||
"for ... in ..." across multiple lines to help make your code more readable.
|
||||
"""
|
||||
|
||||
|
||||
def valid_five_course_schedules(c1: tuple[str, str, set],
|
||||
c2: tuple[str, str, set],
|
||||
c3: tuple[str, str, set],
|
||||
c4: tuple[str, str, set],
|
||||
c5: tuple[str, str, set]) -> list[dict[str, tuple]]:
|
||||
"""Return a list of every valid schedule that contains all given courses.
|
||||
|
||||
This is analogous to valid_schedules, except now there are 5 courses instead of 2.
|
||||
|
||||
Hint:
|
||||
- Use is_valid
|
||||
- Use possible_five_course_schedules
|
||||
|
||||
Preconditions:
|
||||
- all given courses match the format for a course described by the assignment handout.
|
||||
- c1 != c2 and c1 != c3 and c1 != c4 and c1 != c5
|
||||
- c2 != c3 and c2 != c4 and c2 != c5
|
||||
- c3 != c4 and c3 != c5
|
||||
- c4 != c5
|
||||
"""
|
||||
|
||||
|
||||
###################################################################################################
|
||||
# Part 3, Question 3b
|
||||
###################################################################################################
|
||||
def is_section_compatible(schedule: dict[str, tuple[str, str, tuple]],
|
||||
section: tuple[str, str, tuple]) -> bool:
|
||||
"""Return whether the given section is compatible with the given schedule.
|
||||
|
||||
Hint:
|
||||
- Refer to the handout for a definition of compatibility
|
||||
- Use sections_conflict
|
||||
- You can get a collection of only the values of a dict by using dict.values
|
||||
|
||||
Preconditions:
|
||||
- section matches the format for a section described by the assignment handout.
|
||||
- schedule matches the format for a schedule described by the assignment handout.
|
||||
"""
|
||||
|
||||
|
||||
def is_course_compatible(schedule: dict[str, tuple[str, str, tuple]],
|
||||
course: tuple[str, str, set]) -> bool:
|
||||
"""Return whether the given course is compatible with the given schedule.
|
||||
|
||||
Hint:
|
||||
- Refer to the handout for a definition of compatibility
|
||||
- Use is_section_compatible
|
||||
|
||||
Preconditions:
|
||||
- course matches the format for a course described by the assignment handout.
|
||||
- schedule matches the format for a schedule described by the assignment handout.
|
||||
- course[0] not in schedule
|
||||
"""
|
||||
|
||||
|
||||
def compatible_sections(schedule: dict[str, tuple[str, str, tuple]],
|
||||
course: tuple[str, str, set]) -> set[tuple[str, str, tuple]]:
|
||||
"""Return the set of sections of the given course that are compatible with the given schedule.
|
||||
|
||||
Hint:
|
||||
- Refer to the handout for a definition of compatibility
|
||||
- Use is_section_compatible
|
||||
|
||||
Preconditions:
|
||||
- course matches the format for a course described by the assignment handout.
|
||||
- schedule matches the format for a schedule described by the assignment handout.
|
||||
- course[0] not in schedule
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import python_ta
|
||||
import python_ta.contracts
|
||||
python_ta.contracts.DEBUG_CONTRACTS = False
|
||||
python_ta.contracts.check_all_contracts()
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
# When you are ready to check your work with python_ta, uncomment the following lines.
|
||||
# (Delete the "#" and space before each line.)
|
||||
# IMPORTANT: keep this code indented inside the "if __name__ == '__main__'" block
|
||||
# IMPORTANT: Leave this code uncommented when you submit your files.
|
||||
# python_ta.check_all(config={
|
||||
# 'extra-imports': ['datetime', 'python_ta.contracts'],
|
||||
# 'max-line-length': 100,
|
||||
# 'disable': ['R1705', 'R1729']
|
||||
# })
|
||||
@@ -0,0 +1,152 @@
|
||||
"""CSC110 Fall 2020 Assignment 2, Part 4: Processing Raw Course Data
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
This Python module contains the functions you should complete for Part 4 of this assignment.
|
||||
Your task is to complete this module by writing the body of the functions so that they do what
|
||||
their descriptions claim.
|
||||
|
||||
You may, but are not required, to write doctests for this part.
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC110 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC110 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2021 David Liu, Mario Badr, and Tom Fairgrieve.
|
||||
"""
|
||||
import datetime
|
||||
import json
|
||||
|
||||
import a2_part3
|
||||
|
||||
|
||||
###################################################################################################
|
||||
# Part 4: Processing Raw Data
|
||||
###################################################################################################
|
||||
def read_course_data(file: str) -> dict:
|
||||
"""Return a dictionary mapping course codes to course data from the data in the given file.
|
||||
|
||||
In the returned dictionary:
|
||||
- each key is a string representing the course code
|
||||
- each corresponding value is a tuple representing a course value, in the format
|
||||
descried in Part 3 of the assignment handout.
|
||||
|
||||
Note that the implementation of this function provided to you is INCOMPLETE since it just
|
||||
returns a dictionary in the same format as the raw JSON file. It's your job to implement
|
||||
the functions below, and then modify this function body to get the returned data
|
||||
in the right format.
|
||||
|
||||
Preconditions:
|
||||
- file is the path to a JSON file containing course data using the same format as
|
||||
the data in data/course_data_small.json.
|
||||
file is the name (or path) of a JSON file containing course data using the format in
|
||||
the sample file course_data_small.json.
|
||||
"""
|
||||
with open(file) as json_file:
|
||||
data = json.load(json_file)
|
||||
|
||||
return data # TODO: transform data into the format specified in Part 4, then remove this TODO
|
||||
|
||||
|
||||
def transform_course_data(course_data: dict) -> tuple[str, str, set]:
|
||||
"""Transform the given course_data into a tuple representing that course.
|
||||
|
||||
The returned tuple is in the course format described on the assignment handout.
|
||||
|
||||
Preconditions:
|
||||
- course_data is a dictionary containing data about a single course, in the format
|
||||
found in course_data_small.json.
|
||||
"""
|
||||
|
||||
|
||||
def transform_section_data(section_data: dict) -> tuple[str, str, tuple]:
|
||||
"""Transform the given section_data into a tuple representing that section.
|
||||
|
||||
The returned tuple is in the "section" format described on the assignment handout.
|
||||
|
||||
Preconditions:
|
||||
- section_data is a dictionary containing data about a single section, in the format
|
||||
found in course_data_small.json.
|
||||
"""
|
||||
|
||||
|
||||
def transform_meeting_time_data(meeting_time_data: dict) \
|
||||
-> tuple[str, datetime.time, datetime.time]:
|
||||
"""Transform the given meeting_time_data into a tuple representing that section.
|
||||
|
||||
The returned tuple is in the "meeting time" format described on the assignment handout.
|
||||
|
||||
Preconditions:
|
||||
- meeting_time_data is a dictionary containing data about a single meeting time, in the
|
||||
format found in course_data_small.json.
|
||||
|
||||
Hint: The times in the JSON file are length-5 strings in format HH:MM using a 24-hour clock.
|
||||
You'll need to do some string processing to extract the hours and minutes, and convert
|
||||
these to ints and then to a datetime.time. The str.split method is one approach.
|
||||
"""
|
||||
|
||||
|
||||
def get_valid_schedules(course_data: dict[str, tuple[str, str, set]],
|
||||
courses: set[str],
|
||||
term: str) -> list[dict[str, tuple]]:
|
||||
"""Return a list of all valid schedules for the given courses and in the given term.
|
||||
|
||||
courses is a set of course codes; use the given course_data to look up each course code
|
||||
to get the corresponding course tuple.
|
||||
|
||||
All sections in each returned schedule should meet in the given term; 'Y' sections meet
|
||||
in both 'F' and 'S' terms.
|
||||
|
||||
Return an empty list if there are no valid schedules for the given course codes, or if
|
||||
at least one of the courses does not have any sections that meet in the given term.
|
||||
|
||||
Preconditions:
|
||||
- len(courses) == 5
|
||||
- term in {'F', 'S'}
|
||||
- all({course_code in course_data for course_code in courses})
|
||||
|
||||
Hints:
|
||||
1. You can use a2_part3.valid_five_course_schedules.
|
||||
2. You'll need to process each course to filter to keep only the sections
|
||||
that appear in the given term. See the function we've started for you below.
|
||||
"""
|
||||
|
||||
|
||||
def filter_by_term(course: tuple[str, str, set], term: str) -> tuple[str, str, set]:
|
||||
"""Return a copy of the given course with only sections that meet in the given term.
|
||||
|
||||
The returned tuple has the same course code and title as the given course, and its
|
||||
sections set is a subset of the original.
|
||||
|
||||
Note that a 'Y' section meets in BOTH 'F' and 'S' terms, and so should always be
|
||||
included in the returned course tuple.
|
||||
|
||||
Preconditions:
|
||||
- term in {'F', 'S'}
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import python_ta
|
||||
import python_ta.contracts
|
||||
python_ta.contracts.DEBUG_CONTRACTS = False
|
||||
python_ta.contracts.check_all_contracts()
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
# When you are ready to check your work with python_ta, uncomment the following lines.
|
||||
# (Delete the "#" and space before each line.)
|
||||
# IMPORTANT: keep this code indented inside the "if __name__ == '__main__'" block
|
||||
# IMPORTANT: Leave this code uncommented when you submit your files.
|
||||
# python_ta.check_all(config={
|
||||
# 'extra-imports': ['a2_part3', 'datetime', 'json', 'python_ta.contracts'],
|
||||
# 'max-line-length': 100,
|
||||
# 'disable': ['R1705'],
|
||||
# 'allowed-io': ['read_course_data']
|
||||
# })
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"CSC110": {
|
||||
"courseCode": "CSC110",
|
||||
"courseTitle": "Foundations of Computer Science I",
|
||||
"sections": [
|
||||
{
|
||||
"sectionCode": "LEC0101",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0201",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC9101",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC9201",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
{
|
||||
"CSC110": {
|
||||
"courseCode": "CSC110",
|
||||
"courseTitle": "Foundations of Computer Science I",
|
||||
"sections": [
|
||||
{
|
||||
"sectionCode": "LEC0101",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0201",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC9101",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "11:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC9201",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "15:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"CSC111": {
|
||||
"courseCode": "CSC111",
|
||||
"courseTitle": "Foundations of Computer Science II",
|
||||
"sections": [
|
||||
{
|
||||
"sectionCode": "LEC0101",
|
||||
"term": "S",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "14:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "12:00",
|
||||
"endTime": "14:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC9101",
|
||||
"term": "S",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "14:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "12:00",
|
||||
"endTime": "14:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"MAT137": {
|
||||
"courseCode": "MAT137",
|
||||
"courseTitle": "Calculus with Proofs",
|
||||
"sections": [
|
||||
{
|
||||
"sectionCode": "LEC0101",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "10:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "10:00"
|
||||
},
|
||||
{
|
||||
"day": "Friday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "10:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0201",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Thursday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Friday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "11:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0301",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "11:00",
|
||||
"endTime": "12:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "11:00",
|
||||
"endTime": "12:00"
|
||||
},
|
||||
{
|
||||
"day": "Thursday",
|
||||
"startTime": "11:00",
|
||||
"endTime": "12:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0401",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "12:00",
|
||||
"endTime": "13:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "12:00",
|
||||
"endTime": "13:00"
|
||||
},
|
||||
{
|
||||
"day": "Friday",
|
||||
"startTime": "12:00",
|
||||
"endTime": "13:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0501",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "14:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Thursday",
|
||||
"startTime": "14:00",
|
||||
"endTime": "15:00"
|
||||
},
|
||||
{
|
||||
"day": "Friday",
|
||||
"startTime": "14:00",
|
||||
"endTime": "15:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0601",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "10:00"
|
||||
},
|
||||
{
|
||||
"day": "Thursday",
|
||||
"startTime": "09:00",
|
||||
"endTime": "10:00"
|
||||
},
|
||||
{
|
||||
"day": "Friday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "11:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0701",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "14:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "14:00"
|
||||
},
|
||||
{
|
||||
"day": "Friday",
|
||||
"startTime": "13:00",
|
||||
"endTime": "14:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC5101",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "20:00",
|
||||
"endTime": "21:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "20:00",
|
||||
"endTime": "21:00"
|
||||
},
|
||||
{
|
||||
"day": "Thursday",
|
||||
"startTime": "20:00",
|
||||
"endTime": "21:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"MAT157": {
|
||||
"courseCode": "MAT157",
|
||||
"courseTitle": "Analysis I",
|
||||
"sections": [
|
||||
{
|
||||
"sectionCode": "LEC0101",
|
||||
"term": "Y",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Wednesday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "11:00"
|
||||
},
|
||||
{
|
||||
"day": "Friday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "11:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"STA130": {
|
||||
"courseCode": "STA130",
|
||||
"courseTitle": "An Introduction to Statistical Reasoning and Data Science",
|
||||
"sections": [
|
||||
{
|
||||
"sectionCode": "LEC0101",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "12:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0201",
|
||||
"term": "F",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Tuesday",
|
||||
"startTime": "14:00",
|
||||
"endTime": "16:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0101",
|
||||
"term": "S",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "10:00",
|
||||
"endTime": "12:00"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionCode": "LEC0201",
|
||||
"term": "S",
|
||||
"meetingTimes": [
|
||||
{
|
||||
"day": "Monday",
|
||||
"startTime": "14:00",
|
||||
"endTime": "16:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
def replace_color(msg: str) -> str:
|
||||
replacements = ["&0/\033[0;30m", "&1/\033[0;34m", "&2/\033[0;32m", "&3/\033[0;36m", "&4/\033[0;31m", "&5/\033[0;35m", "&6/\033[0;33m", "&7/\033[0;37m", "&8/\033[1;30m", "&9/\033[1;34m", "&a/\033[1;32m", "&b/\033[1;36m", "&c/\033[1;31m", "&d/\033[1;35m", "&e/\033[1;33m", "&f/\033[1;37m", "&r/\033[0m", "&n/\n"]
|
||||
for r in replacements:
|
||||
msg = msg.replace(r[:2], r[3:])
|
||||
return msg
|
||||
|
||||
|
||||
def color(msg: str):
|
||||
print(replace_color(msg + '&r'))
|
||||
Reference in New Issue
Block a user