;;; problem 1a - return the last element of a list

(defun my-last (l)
  (cond ((atom (cdr l)) l)
	((my-last (cdr l)))))

;;; problem 1b - return the last element anywhere in a list

(defun recursive-last (l)
  (cond ((atom (cdr l))
	 (cond ((atom (car l)) l)
	       ((recursive-last (car l)))))
	((recursive-last (cdr l)))))

;;; problem 2a - reverse a list

(defun my-reverse (l)
  (cond ((atom l) nil)
	((append (my-reverse (cdr l))
		 (list (car l))))))

;;; problem 2b - recursively reverse a list (does not handle dotted
;;; lists)

(defun recursive-reverse (l)
  (cond ((atom l) l)
	((append (recursive-reverse (cdr l))
		 (list (recursive-reverse (car l)))))))

;;; problem 2b - recursively reverse a list (handles dotted lists)

(defun recursive-reverse (l)
  (cond ((atom l) nil)
	((append (recursive-reverse (cdr l))
		 (list (cond ((consp (car l)) (recursive-reverse (car l)))
			     ((car l))))))))

;;; problem 3 - flatten a list

(defun flatten (l)
  (cond ((null l) nil)
	((atom l) (list l))
	((append (flatten (car l))
		 (flatten (cdr l))))))

;;; problem 4 - common lisp matchmaker function
;;;
;;; flist1 and flist2 are feature lists of the following form:
;;;   ((key_1 value_1) (key_2 value_2) ... (key_n value_n))
;;;  where key is a string and value may be any s-expression (.e.g,
;;;  atom, number, string, list, etc.).  flist1 and flist2 may be nil.
;;;
;;; mlist is a list of keyword/function pairs of the following form:
;;;   ((key_1 func_1) (key_2 func_2) ... (key_n func_n))
;;; where key is a string and func is a symbol with a function binding.
;;;
;;; count and sum are used to pass to recursive calls the values of the
;;; running count and sum.

(defun compatibility (flist1 flist2 mlist &optional (count 0) (sum 0))
  (cond ((null mlist)
	 (cond ((zerop count) 0.0)
	       ((/ sum count))))
	((compatibility
	  flist1 flist2 (cdr mlist) (1+ count)
	  (+ (apply (cadar mlist)
		    (list (cadr (assoc (caar mlist) flist1 :test #'equal))
			  (cadr (assoc (caar mlist) flist2 :test #'equal))))
	     sum)))))

;;; problem 5a - java matchmaker function (design document)
;;;
;;; The gist of the design document should be the description of an
;;; implementation that essentially recreates the mechanisms by which
;;; Lisp enables an applicative programming environment.  In other
;;; words, in order to accept as input and execute Java source code, a
;;; Java-based replacement must interpret and/or run Java statements
;;; either directly (via an internally constructed interpreter, using
;;; the Reflection API, etc.) or indirectly (via invoking the stock
;;; Java compiler/interpreter on the function specifications).
;;;
;;; The comparison of the Common Lisp and (proposed) Java
;;; implementations should focus on the flexibility of the applicative
;;; programming paradigm versus the imperative/object-oriented
;;; approach.  In particular, acceptable answers to this question
;;; would include the notion that Common Lisp's ability to
;;; augment/modify the execution environment dynamically permits the
;;; programmer to concentrate on high-level design issues rather than
;;; low-level implementation details.  In other words, Lisp adapts
;;; more easily to a potentially changing problem domain than does a
;;; language such as Java.
;;;
;;; Questions to be answered would include: What, specifically, is it
;;; about the two paradigms and/or languages that makes it easier or
;;; harder to solve certain classes of problems? In the context of the
;;; specific problem as well as in general, are there features of one
;;; that the other lacks and vice versa?
;;;
;;; Finally, answers to this question should include specific
;;; references to both the Common Lisp implementation and the proposed
;;; design of the Java implementation.
