Skip to content

Instantly share code, notes, and snippets.

@jadudm
Created November 15, 2015 21:40
Show Gist options
  • Save jadudm/123762e609c8d85ed685 to your computer and use it in GitHub Desktop.
Save jadudm/123762e609c8d85ed685 to your computer and use it in GitHub Desktop.
Upper-division enrollment model (20151115)
(define (new-calc allstu
;; Grad year... for generating new students
;; who will graduate in 2019, by default.
#:grad-year [grad-year 2019]
;; We assume 20 seats per course, default
#:seats-available [seats-available 20]
;; Three upper vision courses per term
#:num-upper-div [num-upper-div 3]
;; Enrollment push from 226 ... represents
;; how many new students enter the pipeline
#:enroll [enroll 67]
;; How many semesters to look forward.
#:semesters [semesters 4]
#:max-per-term [max-per-term 2]
#:cannot-register [cannot-register 5])
;; Grow the number of students we are considering.
;; The function "grow-students" takes the student hash and
;; adds "enroll" new students to that table. By default, we add
;; 67 new students to the table, and all of them need
;; three 3xx courses and one 4xx course.
(define students (grow-students-by allstu enroll grad-year))
;; For each semester we are considering...
;; By default, we consider 4 semesters, or two years from the
;; time they take 226. Semester 0 is a fall semester, so even
;; semesters are when we run primarily 4xx courses.
(for ([sem (range 0 semesters)])
(debug (bracket (format "Semester: ~a" sem)))
;; Calcualte how many seats we have available
(define seats (* seats-available num-upper-div))
;; Now, make multiple passes through, and handle the students
;; with the least time left first. Students with zero semesters
;; left are already done. By default, I'm looping with
;; the time-left variable being valued from 1 to 8.
(for ([time-left (range 1 (add1 (* 2 (- grad-year 2015))))])
(debug (bracket (format "Time Left: ~a" time-left)))
;; For each student
(for ([(name stu) students])
;; Make sure we're considering a student with the "current"
;; amount of time left. This guarantees that seniors get
;; first opportunity to ratchet down the courses they need.
(when (= (hash-ref stu "time-to-grad") time-left)
(debug "~a time left: ~a~n" name time-left)
;; The student now has one less semester remaining.
;; We knock that down by one.
(hash-set! stu "time-to-grad"
(sub1 (hash-ref stu "time-to-grad")))
;; If it is an even semester, we're running mostly
;; 4xx courses. So, we can run down both 4xx and 3xx courses.
;; Students with no time left will have to do this.
;; If it is an odd semester, we can only run down 3xx courses.
(define types (make-parameter '()))
(define labels (make-parameter '()))
(cond
[(even? sem)
(types '("fours" "threes"))
(labels '("4xx" "3xx"))]
[(odd? sem)
(types '("threes"))
(labels '("3xx"))])
;; The reason for this flow is so that, in a term where
;; 4xx courses are offered, we can let students take a
;; 4xx course and have it count as a 3xx in their
;; accounting process.
(for ([type (types)]
[label (labels)])
;; Lets assume students do not take more than
;; (by default) two courses in CSC per term.
(define stu-per-term max-per-term)
;; Lets loop over the number of courses the student has
;; remaining. We're going to do this for every type of
;; course being considered this term. That means, during
;; even terms, we try and take both 4xx and 3xx courses
;; (by using seats in a 4xx course as a proxy).
(let loop ([remaining (hash-ref stu type)])
;; We now know how many courses in this category
;; they need to graduate. When that number
;; is greater than zero, and there are seats, and
;; they're not overloading...
(when (and (> seats 0)
(> remaining 0)
(> stu-per-term 0)
(> (random 100) cannot-register))
;; Remove a seat
(set! seats (sub1 seats))
;; Count down on the number per term
(set! stu-per-term (sub1 stu-per-term))
;; Lower the req for the student
(hash-set! stu type (sub1 (hash-ref stu type)))
(debug "\t~a: ~a -> ~a~n"
name label (hash-ref stu type))
;; Loop with one less
;; We only loop if the "when" statement was true.
;; So, if we run out of seats, or we don't need any
;; more courses in the 3xx or 4xx category, or
;; we can't take any more courses this term (because
;; we only advise 2x per term), we're not going to loop.
(loop (sub1 remaining)))))
))))
;; Now, what's left?
(define needed-threes 0)
(define needed-fours 0)
;; Go through every student in the hash table.
(for ([(name stu) students])
;; Find out how many 3xx and 4xx courses they have left.
(define threes (hash-ref stu "threes"))
(define fours (hash-ref stu "fours"))
;; Increment the global count for each category by the number
;; that the student still has not taken.
(when (> threes 0)
(set! needed-threes (+ threes needed-threes)))
(when (> fours 0)
(set! needed-fours (+ fours needed-fours))))
;; Return two values: the number they need in the 3xx category,
;; and the number in the 4xx category.
(values needed-threes needed-fours)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment