Lab 6 Creating Abstractions
Purpose: This lab focuses on learning to use the built in list functions, map, filter, foldr, foldl, etc. It also gives practice writing code, then going back and adding to it.
Textbook References: Chapter 14: Similarities Everywhere, Chapter 15: Designing Abstractions
As a reminder, here are the signatures for these functions, as well as a simple example using each one. You can find these functions in the book in Figure 95 and Figure 96.
; map: [X Y] [X -> Y] [List-of X] -> [List-of Y] (check-expect (map number->string (list 1 2 3 4)) (list "1" "2" "3" "4")) ; filter: [X] [X -> Boolean] [List-of X] -> [List-of X] (check-expect (filter even? (list 1 2 3 4)) (list 2 4)) ; foldr: [X Y] [X Y -> Y] Y [List-of X] -> Y (check-expect (foldr * 1 (list 1 2 3 4)) 24) ; foldl: [X Y] [X Y -> Y] Y [List-of X] -> Y (check-expect (foldl / 1 (list 1 2 3 4)) 8/3)
Since these functions all take a function as an input, you’re going to need to write helper functions as a part of this lab. Sometimes the exercise will remind you of this, and sometimes it won’t.
None of the exercises in this lab require defining a recursive function. The list functions described above will do the heavy lifting for you. If you are not sure which function above to use, or how to use them, then try designing the functions below using the list-template structure, and then see if you can deduce which abstraction above would help, and rewrite them using the relevant abstraction.
Warmup exercises
Sample Problem Play code detective! Determine the signature for the following functions:
(define (crazy fee fie foe fum) (if (fee (+ fie foe)) fum "Gotcha")) (define (stranger mix match) (mix (mix match)))
Sample Problem Take a look at the following signatures and purpose statements. For each one, determine which existing list abstraction is most appropriate for defining the function.
; [List-of String] -> String ; Appends all the strings in the list together ; [List-of Number] -> Boolean ; Determines whether all the numbers in the list are greater than 100 ; [List-of Posn] -> [List-of Number] ; Produces a list of all the x-values of the posns in the list ; [List-of String] -> Boolean ; Determines whether any string in the list is longer than 140 characters
Warmup: To-do lists
; A TodoList is a [List-of Section] ; A Section is a (make-section String [List-of String]) (define-struct section [title items]) ; INTERPRETATION: A todo list has several titled sections, each with ; some collection of todo items in them.
Exercise 1 Design the function draw-section, that draws a Section as a title (framed, and in larger font) above a rendering of the items in that section. For example,
Use above/align, text and frame for the images, and use an appropriate list abstraction if you can.
Exercise 2 Design the function draw-todo, that draws an entire TodoList, placing each Section beside each other. Use a list abstraction.
Student Grades
We’re going to model students in a class with a simple structure. The initial goal is to store the overall grade of each student.
; A Student is a (make-student String Number). ; where the name is the student's full name, and the grade is a percentage, ; represented as a number between 0 and 100 inclusive. (define-struct student [name grade])
Below are some examples that you should use for your tests.
; Employee number ER28-0652. (define student1 (make-student "Elliot Alderson" 85)) ; Used to go here. (define student2 (make-student "Aaron Turon" 97)) ; Kinda spooky. (define student3 (make-student "Fox Mulder" 69)) ; Likes strawberries. (define student4 (make-student "Kaylee Frye" 82)) ; This "love" intrigues me. Teach me to fake it. (define student5 (make-student "Doctor John E. Zoidberg" 58)) ; students: [List-of Student] (define students (list student1 student2 student3 student4 student5))
Exercise 3 Design a function extra-credit, that takes a Student, and returns a new Student with some amount of points added. The number of points is up to you.
Exercise 4 Design the function extra-credits, that takes a list of Students and returns a new list of Students with each Student given some extra-credit.
Exercise 5 Design the function student-names, that takes a list of Students and returns a list of Strings. The strings are the names of each student.
Exercise 6 Design the function top-students, that takes a list of Students and returns a new list of just the students who are getting A’s, defined to be anyone with a grade above 90.
Exercise 7 Design the function average, that takes a list of Numbers, and returns their average (mean). We’ve done this before, but this time, use list functions.
Exercise 8 Define the function class-average, that takes a list of Students and returns a Number. The number is the average (mean) grade for the whole class of students.
Students Grades Revisited
Now we are going to change the definition of a Student to better track assignments and grades. As you can imagine, storing just the total grade isn’t a very good way to keep a student’s information. Instead we’d really like to know more detail about how a student did on an assignment.
As you have seen, the way assignments get graded is as follows. Start with a total number of points for an assignment, then deduct points for errors. Below are our new data definitions.
If you’d like to have both solutions, feel free to start from a new file, and copy functions from the above exercise as needed.
; A GradedAssignment is a [List-of Number] ; where the first number in the list is the total number of points for the ; assignment, and the rest of the numbers are point deductions from the total. ; Sum up all these numbers to get the actual score on the assignment. ; A GStudent (a Graded Student) is a (make-gstudent String [List-of GradedAssignment]). ; where the name is the student's full name, and graded-assignments is a list ; of all the assignments for the student. (See Alderson, below, for detailed ; example.) (define-struct gstudent [name graded-assignments]) ; Employee number ER28-0652. (define gstudent1 (make-gstudent "Elliot Alderson" (list (list 100 -8 -2 -4 -6) ; 80/100 = 80% (list 60 -2 -4) ; 54/60 = 90% (list 75 -6 -4)))) ; 65/75 = 86.6% ; Used to go here. (define gstudent2 (make-gstudent "Aaron Turon" (list (list 100 -1 -4) (list 60) (list 75 -1)))) ; Kinda spooky. (define gstudent3 (make-gstudent "Fox Mulder" (list (list 100 -10 -6 -4 -4 -4 -4) (list 60 -8 -4 -4 -2 -4) (list 75 -4 -6 -8)))) ; Likes strawberries. (define gstudent4 (make-gstudent "Kaylee Frye" (list (list 100 -4 -8 -2 -4 -4 -1) (list 60 -4 -1 -2 -2 -1) (list 75 -4 -4 -1)))) ; This "love" intrigues me. Teach me to fake it. (define gstudent5 (make-gstudent "Doctor John E. Zoidberg" (list (list 100 -10 -4 -10 -8 -6) (list 60 -10 -8 -10 -2) (list 75 -4 -10 -4 -8 -4)))) ; gstudents: [List-of GStudent] (define gstudents (list gstudent1 gstudent2 gstudent3 gstudent4 gstudent5))
Exercise 9 The first section of the lab defined a function student-grade (where?), and we need an equivalent function for our new GStudents. Design a new function gstudent-grade that takes a GStudent and returns a Number that is the student’s average grade, on a [0,100] scale, across all his or her graded assignments.
You may need to design a few helper functions to help with this exercise.
Exercise 10 Update all the functions from the first section of this lab to work correctly with the new data definitions. Remember to update not just the code, but the signature, purpose statement, and tests too.
Before you go...
If you had trouble finishing any of the exercises in the lab or homework, or just feel like you’re struggling with any of the class material, please feel free to come to office hours and talk to a TA or tutor for additional assistance.