lab08 : BST Course Catalog

num ready? description assigned due
lab08 true BST Course Catalog Sun 11/24 11:59PM Mon 12/02 11:59PM

Introduction

In this lab, you will utilize a Binary Search Tree to store and organize courses.

A course is uniquely identified by its department code and course ID (e.g., CMPSC 9 has the department code "CMPSC" and the course ID 9). In addition to these two attributes, a course also has a course name, a lecture, and several sections.

You will store the details of each course in a binary search tree node defined by class CourseCatalogNode and organize all the courses in a binary search tree defined by class CourseCatalog. The nodes will be ordered first by department code in lexicographical order, and then by course ID in numerical order.

You will also write a test file to verify your implementation. Note: While this lab writeup provides sample test cases for reference, the Gradescope autograder will use different, more complex test cases.

Note: It is important that you start this lab early so you can utilize our office hours to seek assistance / ask clarifying questions during the weekdays before the deadline if needed!

Instructions

You will need to create four files:

Event.py

The Event.py file will contain the definition of the Event class, which is used to represent the lecture and the section. The Event class is structured as follows:

Example:

e1 = Event("TR", (1530, 1645), "td-w 1701")
e2 = Event("TR", (1530, 1645), "td-w 1702")
print(e1 == e2)
print(e1)

Output:

False
TR 15:30 - 16:45, TD-W 1701

🔧 The following is a helper function you can use to convert the time attribute, a (int, int) tuple, to a readable string.

def format(time):
    return f"{time[0]//100:0>2}:{time[0]%100:0>2} - {time[1]//100:0>2}:{time[1]%100:0>2}"

assert format((800, 1550)) == "08:00 - 15:50"

CourseCatalogNode.py

The CourseCatalogNode.py file will contain the definition of the CourseCatalogNode class, which is used to represent a course in a Binary Search Tree. Each node’s key is determined by a course’s department code and course ID. The nodes are ordered first by department code in lexicographical order, followed by course ID in numerical order. The CourseCatalogNode class is structured as follows:

Example:

# create one lecture event
lecture = Event("TR", (1530, 1645), "td-w 1701")

# create four section events
section1 = Event("W", (1400, 1450), "north hall 1109")
section2 = Event("W", (1500, 1550), "north hall 1109")
section3 = Event("W", (1600, 1650), "north hall 1109")
section4 = Event("W", (1700, 1750), "girvetz hall 1112")
sections = [section1, section2, section3, section4]

# initialize a CMPSC 9 course node
node = CourseCatalogNode("cmpsc", 9, "intermediate python", lecture, sections)

print(node)

Output:

CMPSC 9: INTERMEDIATE PYTHON
 * Lecture: TR 15:30 - 16:45, TD-W 1701
 + Section: W 14:00 - 14:50, NORTH HALL 1109
 + Section: W 15:00 - 15:50, NORTH HALL 1109
 + Section: W 16:00 - 16:50, NORTH HALL 1109
 + Section: W 17:00 - 17:50, GIRVETZ HALL 1112

Note that each Event (lecture and sections) will contain a \n character at the end of the line. Also note the single space at the start of each lecture / section line.

CourseCatalog.py

The CourseCatalog.py file will contain the definition of the CourseCatalog class, which is a Binary Search Tree that manages all CourseCatalogNode objects keyed by department and courseId. An example Binary Search Tree structure is illustrated below when the course keys (department and courseId) are inserted in the following order:

  1. CMPSC, 9
  2. CMPSC, 270
  3. CMPSC, 8
  4. PSTAT, 131

example.png

The CourseCatalog class is structured according to the specifications below. Gradescope will test all methods listed below, but your solution can contain (and is recommended to use) additional helper methods that support the functionality.

Example:

cc = CourseCatalog()

# add a new course: cmpsc 9
lecture = Event("TR", (1530, 1645), "td-w 1701")
section1 = Event("W", (1400, 1450), "north hall 1109")
section2 = Event("W", (1500, 1550), "north hall 1109")
section3 = Event("W", (1600, 1650), "north hall 1109")
section4 = Event("W", (1700, 1750), "girvetz hall 1112")
sections = [section1, section2, section3, section4]
assert True == cc.addCourse("cmpsc", 9, "intermediate python", lecture, sections)

# add a new section to cmpsc 9
section5 = Event("F", (0, 2359), "fluent-python-in-one-day hall 101")
assert True == cc.addSection("cmpsc", 9, section5)

# add a new course: art 10
lecture = Event("TR", (1300, 1550), "arts 2628")
sections = []
assert True == cc.addCourse("art", 10, "introduction to painting", lecture, sections)

print("----- in-order traversal -----")
print(cc.inOrder())

print("----- pre-order traversal -----")
print(cc.preOrder())

print("----- post-order traversal -----")
print(cc.postOrder())

print("Task: find all cmpsc 9 sections held on Wednesday and within 15:00 - 17:00 time period")
print(cc.getAttendableSections("cmpsc", 9, "W", (1500, 1700)))

print("Task: count courses by department")
print(cc.countCoursesByDepartment())

Output:

----- in-order traversal -----
ART 10: INTRODUCTION TO PAINTING
 * Lecture: TR 13:00 - 15:50, ARTS 2628
CMPSC 9: INTERMEDIATE PYTHON
 * Lecture: TR 15:30 - 16:45, TD-W 1701
 + Section: W 14:00 - 14:50, NORTH HALL 1109
 + Section: W 15:00 - 15:50, NORTH HALL 1109
 + Section: W 16:00 - 16:50, NORTH HALL 1109
 + Section: W 17:00 - 17:50, GIRVETZ HALL 1112
 + Section: F 00:00 - 23:59, FLUENT-PYTHON-IN-ONE-DAY HALL 101

----- pre-order traversal -----
CMPSC 9: INTERMEDIATE PYTHON
 * Lecture: TR 15:30 - 16:45, TD-W 1701
 + Section: W 14:00 - 14:50, NORTH HALL 1109
 + Section: W 15:00 - 15:50, NORTH HALL 1109
 + Section: W 16:00 - 16:50, NORTH HALL 1109
 + Section: W 17:00 - 17:50, GIRVETZ HALL 1112
 + Section: F 00:00 - 23:59, FLUENT-PYTHON-IN-ONE-DAY HALL 101
ART 10: INTRODUCTION TO PAINTING
 * Lecture: TR 13:00 - 15:50, ARTS 2628

----- post-order traversal -----
ART 10: INTRODUCTION TO PAINTING
 * Lecture: TR 13:00 - 15:50, ARTS 2628
CMPSC 9: INTERMEDIATE PYTHON
 * Lecture: TR 15:30 - 16:45, TD-W 1701
 + Section: W 14:00 - 14:50, NORTH HALL 1109
 + Section: W 15:00 - 15:50, NORTH HALL 1109
 + Section: W 16:00 - 16:50, NORTH HALL 1109
 + Section: W 17:00 - 17:50, GIRVETZ HALL 1112
 + Section: F 00:00 - 23:59, FLUENT-PYTHON-IN-ONE-DAY HALL 101

Task: find all cmpsc 9 sections held on Wednesday and within 15:00 - 17:00 time period
W 15:00 - 15:50, NORTH HALL 1109
W 16:00 - 16:50, NORTH HALL 1109

Task: count courses by department
{'ART': 1, 'CMPSC': 1}

testFile.py

This file should contain tests for all classes and their required methods, written using pytest. Ensure you consider various scenarios and edge cases when designing your tests. Every method of each class should be tested.

While Gradescope will not execute this file during automated testing, you can run it locally to debug and verify that your code functions correctly. Please remember, testing is important!

Submission

Once you have completed your class definitions and tests, submit the following files to Gradescope’s Lab08 assignment:

Gradescope will run a variety of unit tests to verify that your code works correctly according to the specifications provided in this lab.

If the tests don’t pass, you may get some error messages that may not be immediately clear. Don’t worry — take a moment to consider what might have caused the error, and double-check the instructions to ensure your code is following the specifications precisely. Consider writing additional test cases for various scenarios / edge cases to help you debug any issues. If you’re still unsure why the error is occurring, feel free to ask your TAs or Learning Assistants for assistance.

* Lab08 created by Jiajun Wang and Ysabel Chen, and adapted / updated by Richert Wang (F24)