UNB/ CS/ David Bremner/ teaching/ cs2613/ assignments/ CS2613 Assignment 2

Background

What to hand in, and how to hand it in

Marking

Getting Started

(require xml)
(define (load-xexpr path)
  (xml->xexpr (document-element (read-xml (open-input-file path)))))
(require explorer)
(define data (load-xexpr "rubrics.xml"))
(explore data)

What forms to use

Other than the given use of read-xml, xml->expr, and any use of explore for visualization, you should only use forms (functions and macros) provided by #lang racket (and those you write yourself).

Questions

Q1 Loading the rubrics

(module+ test
  (require rackunit)
  (define rubrics (load-rubrics  "rubrics.xml"))
  (check-equal? (length rubrics) 5)
  (for ([elt rubrics])
    (check-equal? (first elt) 'rubric)))

Q2 Improving assoc

Racket has a built in function assoc that is useful for doing searches of lists

> (assoc 3 (list (list 1 2) (list 3 4) (list 5 6)))

'(3 4)
> (assoc 9 (list (list 1 2) (list 3 4) (list 5 6)))

#f

For our XML parsing purposes we want to make two tweaks to how this function works. First, we want to ignore top level elements that are not lists. Second, we want to return just the value part of the sublist (key value). Use match to write a function assoc* that passes the following tests (note the use of assoc* to extract the rubric name).

(module+ test
  (define test-list '(1 [keep 2] 3 [keep 4] [keep 5] 6))
  (check-equal? (assoc* 'keep test-list) 2)
  (check-equal? (assoc* 'discard test-list) #f))

(define (rubric-name rubric)
  (assoc* 'name (second rubric)))

(module+ test
  (check-equal?
   (sort (map rubric-name rubrics) string<=?)
   '("JavaScript Assignment" "Journal Entry" "Octave Assignment" "Python Assignment"
                             "Racket assignment")))

Q3 Keep all the pairs

Another useful extension to assoc is to have it return all the matching pairs. Write a tail-recursive function assoc-all that passes the following tests.

(module+ test
  (check-equal? (assoc-all 'keep test-list) '([keep 2] [keep 4] [keep 5])))

(define (criteria-groups rubric)
  (assoc-all 'criteria_group
             (assoc 'criteria_groups (rest rubric))))

(module+ test
  ;; Journals have one group, others have 2
  (check-equal? (sort (map length (map criteria-groups rubrics)) <=)
                '(1 2 2 2 2))
  (check-equal?
   (first ;; tag
    (first ;; first criteria group
     (criteria-groups (first rubrics))))
   'criteria_group))

Q4 Extracting criteria levels

Use assoc-all and other appropriate list functions to write function criteria-levels passing the following tests

(module+ test
  (for ([level  (criteria-levels (first (criteria-groups (first rubrics))))])
    (check-equal? (first level) 'level)))

Q5 Reformatting level information

Write a function level-name-score that extracts the level name and value, and passes the following test

(module+ test
  (check-equal? (map level-name-score (criteria-levels (first (criteria-groups (first rubrics)))))
                '(("Needs improvement" 0)
                  ("Minimally satifactory" 1)
                  ("Good" 2)
                  ("Excellent" 3))))