## Test Scores

### May 24, 2016

We begin by creating test input:

(define scores '(("Alice" 84) ("Bob" 92) ("Alice" 93)
("Bob" 47) ("Charlie" 73) ("Dennis" 59) ("Eve" 91)
("Alice" 78) ("Charlie" 85) ("Eve" 68) ("Alice" 100)
("Charlie" 84) ("Dennis" 92) ("Eve" 85) ("Dennis" 83)
("Alice" 92) ("Bob" 68) ("Bob" 79) ("Dennis" 79)
("Alice" 84) ("Bob" 89) ("Charlie" 69) ("Charlie" 67)
("Charlie" 92) ("Dennis" 73) ("Eve" 79) ("Eve" 84)))

Processing occurs in two steps: First, we accumulate lists of scores for each student in an R6RS hash table. Second, we sort the scores, then take the average of the top five:

(define (score scores)
(let ((ht (make-hashtable string-hash string=?)))
(do ((scores scores (cdr scores)))
((null? scores))
(hashtable-set! ht (caar scores)
(hashtable-ref ht (caar scores) (list)))))
(call-with-values
(lambda () (hashtable-entries ht))
(lambda (key value)
(map (lambda (key value)
(list key (/ (sum (take 5 (sort > value))) 5.)))
(vector->list key) (vector->list value))))))

Here’s the output for our sample data:

> (score scores)
(("Dennis" 77.2)
("Eve" 81.4)
("Alice" 90.6)
("Charlie" 80.6)
("Bob" 75.0))

We used take and sum from the Standard Prelude. You can run the program at http://ideone.com/ux59n2, where you will see that Guile Scheme uses a different set of hashtable functions than standard R6RS, and takes the arguments to sort in a different order.

Pages: 1 2

### One Response to “Test Scores”

1. Rainer said

In SQL for DB2:

with students (id,name) as (values
(1, 'A'),(2, 'B'),(3, 'C')),
scores (id,score,cnt) as
(select id, int(rand() * 100), 1
from   students
union  all
select id, int(rand() * 100), cnt + 1
from   scores
where  cnt < 10),
list (id,cnt,arr) as
(select id,cnt,cast(char(score) as varchar(50))
from   scores
where  cnt = 1
union  all
select s.id,s.cnt,trim(l.arr) concat ',' concat char(s.score)
from   list l
inner  join scores s on l.id = s.id and l.cnt + 1 = s.cnt),
hits (id,score,rn) as
(select id,score,row_number() over
(partition by id order by score desc)
from   scores),
average (id,val) as
(select id, avg(score)
from   hits
where  rn <= 5
group  by id)
select a.id as student_id,
a.val as average_score,
l.arr as scores_list
from   average a
inner  join list l
on     a.id = l.id and l.cnt = 10

==>

STUDENT_ID   AVERAGE_SCORE   SCORES_LIST
1              55   49,49,18,35,15,70,45,7,63,33
2              80   79,59,30,4,79,90,21,61,61,92
3              68   54,42,30,65,59,39,82,18,84,39