Last active
October 7, 2025 01:31
-
-
Save jonathanvdc/ed402f7c473853a9c18af7a1d9ffdfb4 to your computer and use it in GitHub Desktop.
COMP302 Lab 5 - Skeleton
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (* Part 1 *) | |
| (* WARM UP: practicing using references -- imperative programming *) | |
| (* REMINDER | |
| Fibonacci is a sequence of numbers defined as follows: | |
| - fib(0) = 0 | |
| - fib(1) = 1 | |
| - For n >= 2, fib(n) = fib(n - 1) + fib(n - 2) | |
| Very early in the course, | |
| we saw a much faster of computing the nth item in the sequence by iterating the transformation | |
| a, b -> b, a+b | |
| starting on the initial conditions `a=0`, `b=1`. | |
| We saw that this tail-recursive implementation of fib... | |
| *) | |
| let rec fib n a b = if n = 0 then a else fib (n-1) b (a+b) | |
| (* was equivalent, after tail-call optimization, to this Python program using a while loop. | |
| def fib(n, a, b): | |
| while n > 0: | |
| a, b = b, a+b | |
| n -= 1 | |
| return a | |
| *) | |
| (* Well now we can translate this Python program, using genuinely mutable variables, back into | |
| OCaml! *) | |
| let fib n a b = | |
| let n = ref n in | |
| let a = ref a in | |
| let b = ref b in | |
| while !n > 0 do | |
| let c = !a + !b in | |
| a := !b; | |
| b := c; | |
| n := !n - 1; | |
| done; | |
| !a | |
| (* DISCUSS: why the three lines setting up mutable variables within the function `fib`? | |
| If we removed those, how does our program compare to the Python version? *) | |
| (* Follow-up: now use tuples inside the ref-cell to represent the state. *) | |
| let fib n a b = | |
| let state = failwith "Not implemented yet" | |
| (* Part 2 *) | |
| (* A minimal OOP example *) | |
| type counter = { | |
| inc : unit -> unit; | |
| get : unit -> int; | |
| } | |
| let make_counter (initial : int) : counter = | |
| let value = ref initial in | |
| let inc () : unit = value := !value + 1 in | |
| let get () : int = !value in | |
| { inc; get } | |
| (* Part 3 *) | |
| (* OOP with Lists & Options *) | |
| (* In the next section, we will build a grade managing system that will | |
| keep track of grades for up to 5 courses. The system will include | |
| functionalities such as adding courses, updating grades, retrieving course | |
| averages, and resetting all records. *) | |
| (* PRELUDE *) | |
| exception NoSuchCourse | |
| exception TooManyCourses | |
| type name = string | |
| type course = name * (float * int) | |
| type courses = course list | |
| (* The course tracker type, exposing operations for managing courses *) | |
| type course_tracker = { | |
| add_course : name -> unit; | |
| add_grade : name -> float -> unit; | |
| get_average : name -> float; | |
| list_courses: unit -> courses; | |
| reset : unit -> unit; | |
| } | |
| (* Helper: Checks if a course exists using List.exists *) | |
| let course_exists (courses : courses) (course_name : name) : bool = | |
| List.exists (fun (name, _) -> name = course_name) courses | |
| (* Helper: Finds a course by name and returns its (average, count), or None if not found *) | |
| let find_course (courses : courses) (course_name : name) : (float * int) option = | |
| match List.find_opt (fun (name, _) -> name = course_name) courses with | |
| | None -> None | |
| | Some (_, info) -> Some info | |
| (* Helper: Transforms the course with the given name according to a given function. *) | |
| let map_course (f : course -> course) (course_name : name) (courses : courses) : courses = | |
| List.map (fun c -> if fst c = course_name then f c else c) courses | |
| (* We will be implementing the following functionalities: | |
| 1. List Courses | |
| - Return list containing current courses, including current averages | |
| and number of assignments. | |
| 2. Resetting the System: | |
| - Provide functionality to reset the system by clearing all course records, | |
| allowing the user to start afresh. | |
| 3. Retrieving Course Averages: | |
| - Implement a function that returns the current average for a specified course. | |
| - If the course does not exist, the system will throw the ClassNotExist exception. | |
| 4. Adding Courses: | |
| - Allow the user to add a new course to the grade managing system. | |
| - Each course is stored as a tuple containing the course name and a pair | |
| representing its current average and the count of assignments. | |
| - The system supports up to 5 courses. | |
| - If the user tries to add another course when there are already 5 courses, | |
| the system will throw the TooManyCourses exception. | |
| - If an empty course name is provided or the course already exists, | |
| appropriate exceptions will be raised or the operation will be a no-op. | |
| 5. Adding Grades: | |
| - Provide a function to add a grade for an existing course. | |
| - If the course does not exist, the system will throw the ClassNotExist exception. | |
| - We assume that every assignment has the same weight. | |
| - When a grade is added, the system updates the course's weighted average. | |
| - The weighted average is updated using the formula: | |
| new_avg = ((old_avg * old_number_assignments) + new_grade) / (new_number_assignments) | |
| - Here, new_number_assignments equals old_number_assignments + 1. | |
| - If the updated average falls below 55.0, the system will print to the console using print_endline "Risk of Failing" | |
| *) | |
| let make_course_tracker () : course_tracker = | |
| let courses = ref [] in | |
| let add_course (course_name : string) : unit = failwith "Not implemented yet" in | |
| let add_grade (course_name : string) (grade : float) : unit = failwith "Not implemented yet" in | |
| let get_average (course_name : string) : float = failwith "Not implemented yet" in | |
| let list_courses () : courses = failwith "Not implemented yet" in | |
| let reset () : unit = failwith "Not implemented yet" in | |
| { add_course; add_grade; get_average; list_courses; reset } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment