;; My solution (named interp-dave). ;; Used to compare with student's interp function. ;; helper function is named getval ;; getval consumes either a list or a number and produces a number. ;; ;; (getval e) determines whether e is a number or a list. ;; if it is a number, the number is returned. ;; if e is a list, getval evaluates the list by calling ;; interp on it and returns the value produces by interp (define (getval e) (cond [(list? e) (interp e)] [(number? e) e] [ else (error 'geval "Unknown thingy!")])) ;; ============================================================ ;; NOTE: for grading this is called interp-dave, but this is the ;; same function as interp... ;; interp consumes a list and produces a number. ;; ;; (interp l) evaulate lists that contain elements according to the ;; rules below. Note that each list l described some computation to ;; be performed, interp does this computation. ;; ;; valid lists contain 3 elements. The middle element must be one of ;; the following: 'plus, 'minus, 'times, 'div. These correspond to the ;; arithmetic operations addition, subtraction, multplication and division. ;; ;; the first and last elements of l must either be numbers, or lists ;; which follow the same rules as the format for l. ;; ;; sample usage: ;; (interp '(3 plus 5)) (define (interp-dave l) (cond ;; doing addition? if so use getval to evaluate the first and third ;; elements of l, then do the addition [(symbol=? (first (rest l)) 'plus) (+ (getval (first l)) (getval (third l)))] ;; doing subtraction? if so use getval to evaluate the first and third ;; elements of l, then do the subtraction [(symbol=? (first (rest l)) 'minus) (- (getval (first l)) (getval (third l)))] ;; doing multiplication? if so use getval to evaluate the first and third ;; elements of l, then do the multiply [(symbol=? (first (rest l)) 'times) (* (getval (first l)) (getval (third l)))] ;; doing division? if so use getval to evaluate the first and third ;; elements of l, then do the divide [(symbol=? (first (rest l)) 'div) (/ (getval (first l)) (getval (third l)))] [ else ;; oops - unknown operator (error 'interp "Unknown operator")])) ;; ;; ============================================================= ;; CODE BELOW IS USED FOR TESTING INTERP FUNCTIONS ;; ;; code to generate random expressions and test student's interp function ;; num prob is the probability of generating a random number in an expression ;; rather than generating a nested expression. Set to 20% now. (define numprob 20) ;; ;; generate_quiz5_test consumes a number and produces a list. ;; ;; (generate_quiz5_test num) generates a list that can be fed to ;; an interp function. The list may include nested lists (expressions), ;; the maximum depth of these expressions is controlled by num. ;; ;; This function generates a single (non-nested) expression if num is 0. ;; In this case it randomly picks an operator and two numbers in the range ;; [-500,-1],[1,500] - it avoids zero so we don't have to worry about possible ;; division by 0. ;; ;; If num is > 0, the list generated will have a random operator, and with probability ;; numprob (defined above) will generate a random number as the left/right values of the ;; expression. With probability 100-numprob, the left(right) will not be a number, but will ;; instead be another expression (created recursively with num set to num-1). (define (generate_quiz5_test num) (cond ;; hit max depth - generate leaf expression [(= num 0) (quiz5_random_expression)] [ else ;; not maximum depth - generate a possibly complex expression (list ;; first element is a number with probability numprob, ;; an expression with probability 100-numprob. (cond [ (< numprob (random 100)) (generate_quiz5_test (- num 1))] [ else (random-num) ]) ;; pick random operator (random-op) ;; third element follows same strategy as the first (cond [ (< numprob (random 100)) (generate_quiz5_test (- num 1))] [ else (random-num) ]))])) ;; generates a flat (non-nested) random expression (define (quiz5_random_expression ) (list (random-num) (random-op) (random-num))) ;; generates 1 or -1 randomly (used to generate random numbers that can't be 0) (define (randomsign) (cond [(even? (random 2)) 1] [ else -1])) ;; avoid zero (so we don't divide by 0!) (define (random-num) (* (randomsign) (+ 1 (random 500)))) ;; pick an operator randomly (define (random-op) (list-select '(plus minus times div) (random 4))) ;; used to pick random operator from list (define (list-select alist pos) (cond [(empty? alist) (error 'list-select "Problem selecting an operator")] [(= 0 pos) (first alist)] [ else (list-select (rest alist) (- pos 1))])) ;; ;; ;; main testing function - runs both interp-dave and interp on an ;; expression and compares the results. (define (quiz5-runtest exp) (= (interp-dave exp) (interp exp))) ;; result of this should be 10 trues (quiz5-runtest (generate_quiz5_test 1)) (quiz5-runtest (generate_quiz5_test 2)) (quiz5-runtest (generate_quiz5_test 3)) (quiz5-runtest (generate_quiz5_test 4)) (quiz5-runtest (generate_quiz5_test 5)) (quiz5-runtest (generate_quiz5_test 6)) (quiz5-runtest (generate_quiz5_test 7)) (quiz5-runtest (generate_quiz5_test 8)) (quiz5-runtest (generate_quiz5_test 9)) (quiz5-runtest (generate_quiz5_test 10)) ;; make sure they check the operator (should generate an error) (interp '(4 blah 22))