CSCI 316: Lisp Assignment 3

This document includes Kong’s official Scheme solutions that were posted after the submission deadline. They have been translated to Common Lisp by an LLM.

Due Date: Tuesday, October 21

Prerequisite: Complete Lisp Assignment 2 first

Submissions after this due date will be accepted as late submissions until a late-submission deadline in December that will be announced later. See page 3 of the 1st-day announcements document for information on late-submission penalties.

Important: Students should have entered source /home/faculty/ykong/316setup at the xxxxx_yyyy316@mars:~$ prompt weeks ago. You won’t be able to submit this assignment unless you have done that!

Assignment Details:

Coding Requirements:

Assigned Problems

  1. Define a LISP function MIN-2 with the following properties:

    MIN-2 takes two arguments, A and B.

    • If A and B are numbers such that A ≤ B, then MIN-2 returns A
    • If A and B are numbers such that A > B, then MIN-2 returns B
    • If A or B is not a number, then MIN-2 returns the symbol ERROR

    Examples:

    (MIN-2 21.3 7/2) => 7/2
    (MIN-2 17.5 29) => 17.5
    (MIN-2 5 'APPLE) => ERROR
    (MIN-2 '(31) '(54)) => ERROR
    
    Scheme Solution
    (define (min-2 a b)
      (cond ((not (real? a)) 'error)
            ((not (real? b)) 'error)
            ((<= a b) a)
            (else b)))
    
    Common Lisp Solution
    (defun min-2 (a b)
      (cond ((not (realp a)) 'error)
            ((not (realp b)) 'error)
            ((<= a b) a)
            (t b)))
    
  2. [Exercise 4 on p. 72 of Wilensky] Write a LISP function SAFE-AVG that takes 2 arguments and returns the average of those arguments if they are numbers. If one or both of the arguments is not a number, the function should return NIL.

    Examples:

    (SAFE-AVG 23 47.4)  => 35.2
    (SAFE-AVG 3 8)  => 11/2
    (SAFE-AVG '(23.1) 47.3)  => NIL
    (SAFE-AVG 'ORANGE 'PLUM)  => NIL
    
    Scheme Solution
    (define (safe-avg x y)
      (and (number? x) (number? y) (/ (+ x y) 2)))
    
    Common Lisp Solution
    (defun safe-avg (x y)
      (and (numberp x) (numberp y) (/ (+ x y) 2)))
    
  3. [Exercise 2 on p. 72 of Wilensky] Write a LISP predicate ODD-GT-MILLION that takes one argument, and which returns T if its argument is an odd integer greater than a million, but returns NIL otherwise.

    Hint: Make use of the predicate INTEGERP.

    Examples:

    (ODD-GT-MILLION 92010231) => T
    (ODD-GT-MILLION 17) => NIL
    (ODD-GT-MILLION 92010232) => NIL
    (ODD-GT-MILLION 21/5) => NIL
    (ODD-GT-MILLION 1718671.24) => NIL
    (ODD-GT-MILLION '(2010231)) => NIL
    (ODD-GT-MILLION 'APPLE) => NIL
    
    Scheme Solution
    (define (odd-gt-million x)
      (and (integer? x) (> x 1000000) (odd? x)))
    
    Common Lisp Solution
    (defun odd-gt-million (x)
      (and (integerp x) (> x 1000000) (oddp x)))
    
  4. [Exercise 3 on p. 72 of Wilensky] Write a LISP predicate MULTIPLE-MEMBER that takes two arguments and behaves as follows: If the first argument is a symbol or number and the second is a list, then MULTIPLE-MEMBER returns a non-null value if the first argument occurs at least twice in the second argument, but returns NIL otherwise.

    Examples:

    (MULTIPLE-MEMBER 'A '(B A B B A C A D)) => (A C A D)
    (MULTIPLE-MEMBER 3 '(B 3 B B C C 3 D)) => (3 D)
    (MULTIPLE-MEMBER 3 '(B 3 B B C D)) => NIL
    (MULTIPLE-MEMBER 'A '(B C D)) => NIL
    

    Note: The behavior of MULTIPLE-MEMBER is unspecified in cases where the first argument is not a symbol or number, and in cases where the second argument is not a list. Your definition may therefore return any value or produce an evaluation error in such cases.

    Scheme Solution
    ;;; The following helping function for multiple-member
    ;;;   has the property that (safe-cdr #f) => (), so
    ;;;   (safe-cdr (member x l)) => () if (member x l) => #f.
    ;;; In Common Lisp, cdr can be used instead of safe-cdr,
    ;;;   because in Common Lisp (cdr nil) => nil and so
    ;;;   (cdr (member x l)) => nil if (member x l) => nil.
    ;;;
    (define (safe-cdr l)
      (if (pair? l) (cdr l) '()))
    ;;;
    (define (multiple-member x l)
      (member x (safe-cdr (member x l))))
    
    Common Lisp Solution
    (defun multiple-member (x l)
      (member x (cdr (member x l))))
    
  5. Define a LISP function MONTH->INTEGER which takes as argument a symbol that should be the name of a month, and which returns the number of the month.

    Examples:

    (MONTH->INTEGER 'MARCH) => 3
    (MONTH->INTEGER 'JUNE) => 6
    

    If the argument is not a symbol that is the name of a month, the function should return the symbol ERROR.

    Examples:

    (MONTH->INTEGER 'C) => ERROR
    (MONTH->INTEGER 7) => ERROR
    (MONTH->INTEGER 'QUOTE) => ERROR
    (MONTH->INTEGER '(MAY)) => ERROR
    
    Scheme Solution
    (define (month->integer m)
      (cond ((equal? m 'january) 1)
            ((equal? m 'february) 2)
            ((equal? m 'march) 3)
            ((equal? m 'april) 4)
            ((equal? m 'may) 5)
            ((equal? m 'june) 6)
            ((equal? m 'july) 7)
            ((equal? m 'august) 8)
            ((equal? m 'september) 9)
            ((equal? m 'october) 10)
            ((equal? m 'november) 11)
            ((equal? m 'december) 12)
            (else 'error)))
    
    Common Lisp Solution
    (defun month->integer (m)
      (cond ((equal m 'january) 1)
            ((equal m 'february) 2)
            ((equal m 'march) 3)
            ((equal m 'april) 4)
            ((equal m 'may) 5)
            ((equal m 'june) 6)
            ((equal m 'july) 7)
            ((equal m 'august) 8)
            ((equal m 'september) 9)
            ((equal m 'october) 10)
            ((equal m 'november) 11)
            ((equal m 'december) 12)
            (t 'error)))
    
  6. Define a LISP function SCORE->GRADE which takes a single argument, s, and returns a symbol according to the following scheme:

    Range Grade
    s ≥ 90 A
    87 ≤ s < 90 A–
    83 ≤ s < 87 B+
    80 ≤ s < 83 B
    77 ≤ s < 80 B–
    73 ≤ s < 77 C+
    70 ≤ s < 73 C
    60 ≤ s < 70 D
    s < 60 F

    If the argument s is not a number then the function should return NIL.

    Examples:

    (SCORE->GRADE 86.3) => B+
    (SCORE->GRADE 106) => A
    (SCORE->GRADE 10.1) => F
    (SCORE->GRADE 59.9) => F
    (SCORE->GRADE 83) => B+
    (SCORE->GRADE 74) => C+
    (SCORE->GRADE 67) => D
    (SCORE->GRADE 87.0) => A
    (SCORE->GRADE '(86.3)) => NIL
    (SCORE->GRADE 'DOG) => NIL
    
    Scheme Solution
    (define (score->grade s)
      (cond ((not (real? s)) 'nil)
            ((>= s 90) 'a)
            ((>= s 87) 'a-)
            ((>= s 83) 'b+)
            ((>= s 80) 'b)
            ((>= s 77) 'b-)
            ((>= s 73) 'c+)
            ((>= s 70) 'c)
            ((>= s 60) 'd)
            (else 'f)))
    
    Common Lisp Solution
    (defun score->grade (s)
      (cond ((not (realp s)) nil)
            ((>= s 90) 'a)
            ((>= s 87) 'a-)
            ((>= s 83) 'b+)
            ((>= s 80) 'b)
            ((>= s 77) 'b-)
            ((>= s 73) 'c+)
            ((>= s 70) 'c)
            ((>= s 60) 'd)
            (t 'f)))
    

Problems 7–9: Without COND, IF, WHEN, UNLESS, or CASE

Solve problems 7–9 below without using COND, IF, WHEN, UNLESS or CASE.

Note: WHEN, UNLESS, and CASE have not been covered in this course, so students are not expected to have any knowledge of those three macros.

Reminder: Do not use COND, IF, WHEN, UNLESS or CASE when solving the three problems below.

  1. Define a LISP function GT with the following properties:

    GT takes two arguments. It returns T if the arguments are numbers and the first argument is greater than the second; otherwise it returns NIL.

    Examples:

    (GT 0 1) => T
    (GT 3 7) => T
    (GT 40 40) => NIL
    (GT 'B 'A) => NIL
    

    Remember: Do not use COND, IF, WHEN, UNLESS, or CASE!

    Scheme Solution
    (define (gt x y)
      (and (real? x) (real? y) (> x y)))
    
    Common Lisp Solution
    (defun gt (x y)
      (and (realp x) (realp y) (> x y)))
    
  2. Define a LISP function SAME-PARITY with the following properties:

    SAME-PARITY takes two arguments. It returns T if both arguments are even integers or if both arguments are odd integers. In all other cases SAME-PARITY returns NIL.

    Examples:

    (SAME-PARITY 0 1) => NIL
    (SAME-PARITY 3 9) => T
    (SAME-PARITY 30 90) => T
    (SAME-PARITY 'A 3) => NIL
    (SAME-PARITY 4 3.7) => NIL
    
    Scheme Solution
    (define (same-parity x y)
      (and (integer? x)
           (integer? y)
           (or (and (even? x) (even? y))
               (and (odd? x) (odd? y)))))
    
    Common Lisp Solution
    (defun same-parity (x y)
      (and (integerp x)
           (integerp y)
           (or (and (evenp x) (evenp y))
               (and (oddp x) (oddp y)))))
    
  3. Define a LISP function SAFE-DIV with the following properties:

    SAFE-DIV takes two arguments. If both arguments are numbers and the second does not satisfy ZEROP, then the function returns the result of dividing the first argument by the second. In all other cases it returns NIL.

    Examples:

    (SAFE-DIV 6 4) => 3/2
    (SAFE-DIV 6.0 4) => 1.5
    (SAFE-DIV 6 0) => NIL
    (SAFE-DIV 6 0.0) => NIL
    (SAFE-DIV '(6) 4) => NIL
    (SAFE-DIV 6 T) => NIL
    
    Scheme Solution
    (define (safe-div x y)
      (and (number? x)
           (number? y)
           (not (zero? y))
           (/ x y)))
    
    Common Lisp Solution
    (defun safe-div (x y)
      (and (numberp x)
           (numberp y)
           (not (zerop y))
           (/ x y)))
    

Submission Instructions

See submission-instructions.md for general submission guidelines that apply to all Lisp assignments.

Assignment-Specific Notes

In this document, the term list should be understood to mean proper list.

Wrongly named functions (e.g., a function for problem 5 named MNTH->INTEGER or MONTH-INTEGER instead of MONTH->INTEGER) are likely to receive no credit!

Unless you are running Clisp as a subprocess of emacs, each time you write or modify a function it is good to:

Questions about the problems that are emailed to me will not be answered before the submission deadline.

Note: This assignment counts 0.6% towards your grade if the grade is computed using Rule A.