ITERATION ON NUMBERS AND LISTS --------------------------------------------------------------------- DOTIMES Supports Iteration on Numbers (dotimes <(count parameter> <upper-bound form> <result form>) <body>) (defun dotimes-expt (m n) (let ((result 1)) ;Initialize result parameter. (dotimes (count n result) ;Evaluate body N times. (setf result (* m result))))) ;Multiply by M again. 題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題 7-1: Defines DOTIMES-FACTORIAL, using a DOTIMES form. Factorial of n is 1, if n is 0, and n times the factorial of (n-1) otherwise. That is: n! = n * (n-1)!, for n>0; n! = 1, for n=0. --------------------------------------------------------------------------- DOLIST Supports Iteration on Lists (dolist (<element parameter> <list form> <result form>) <body>) * (count-layers '(18 75 31 180 270 52)) 3 (setf freezing 32 boiling 212) (defun count-layers (list-of-elements) (let ((result 0)) ;Initialize result parameter. (dolist (element list-of-elements ;Establish DOLIST parameter. result) ;Result form. (when (or (> element boiling) ;Test element against high. (< element freezing) ;Test element against low. (setf result (+ result 1)))))) ;Increment result. (defun first-n-outlyers (n list-of-elements) (let ((result 0) ;Initialize result. (outlyers nil)) ;Initialize result. (dolist (element list-of-elements ;Establish DOLIST parameter. outlyers) ;Result form (cond ((or (> element boiling) ;Test element against high. (< element freezing)) ;Test element against low. (setf result (+ result 1)) ;Increment result. (push element outlyers)) ;Add element to the result. ((= n result) (return outlyers)))))) ;Stop when N found. (defun clear-top (object) (dolist (obstacle <list of things the object supports> t> (get-rid-of obstacle))) 題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題 7-2: Write COUNT-OUTYERS-WITH-COUNT-IF using COUNT-IF instead of DOLIST. ------------------------------------------------------------------------- 7-3: Write LIST-OUTLYERS, a procedure that lists the elements in a list that are below the freezing point of water, FREEZING, or above the boiling point, BOILING. While you could do this using REMOVE-IF-NOT, do it instead using DOLIST. ------------------------------------------------------------------------ 7-4: Write LIST-OUTLYER-COUNTS, a procedure that counts the temperatures below freezing and above boiling separately, returning a list of the two counts. While you could do this with two separate calls involving COUNT-IF, do it instead using DOLIST. ----------------------------------------------------------------------- 7-5: Ignoring the existence of MEMBER, write DOLIST-MEMBER, an iterative version of recursive-member: (defun revursive-member (item l) (cond ((endp l) nil) ((eql item (first l)) t) (t (recursive-member item (rest l))))) Note that both RECURSIVE-MEMBER and your solution, unlike MEMBER, are to reutrn T when an item is found. ----------------------------------------------------------------------- 7-6: Ignoring the existence of Reverse, write DOLIST-REVERSE using DOLIST. -------------------------------------------------------------------------- DO Is More General than DOLIST and DOTIMES (defun do-expt (m n) (do ((result 1) ;Bind parameters. (exponent n)) ;Bind parameters. ((zerop exponent) result) ;Test and reeutrn. (setf result (* m result)) ;Body. (setf exponent (- exponent 1)))) ;Body. (defun do-expt (m n) (do ((result 1) ;Bind parameters. (exponent n)) ;Bind parameters. () ;Test always fails. (when (zerop exponent) ;Test. (return result)) ;Return. (setf result (* m result)) ;Body. (setf exponent (- exponent 1)))) ;Body. (defun do-expt (m n) (do ((result 1 (* m result)) ;Bind and update parameters. (exponent n (- exponent 1))) ;Bind and update parameters. ((zerop exponent) result))) ;Test and return. (DO ((<parameter 1> <initial value 1> <update form 1>) (<parameter 2> <initial value 2> <update form 2>) ... (<parameter n> <initial value n> <update form n>)) (<Termination test> <intermediate forms, if any> <result form>) <body>) (defun do-expt (m n) (do ((result m (* m result)) ;Bugged!. (exponent n (- exponent 1)) ;RESULT starts as m not 1. (counter (- exponent 1) ;Value of COUNTER is one less (- exponent 1))) ;then value of EXPONENT. ((zerop counter) result))) 題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題 7-7: Define D0-FACTORIAL, using a DO form with an empty body. --------------------------------------------------------------------- 7-8: Ignoring the existence of MEMBER, write DO-MEMBER, an iterative version of RECURSIVE-MEMBER using DO. Like MEMEBER, DO-MEMBER is to return the remainder of the list when the item is encountered: (defun recursive-member (item 1) (cond ((endp l) nil) ((eql item (first l)) l) (t (recursive-member item (rest l))))) -------------------------------------------------------------------- 7-9: Ignoring the existence of REVERSE, a primitive supplied by Lisp, write DO-RESERVE using DO. --------------------------------------------------------------------- (LOOP <body>) -------------------------------------------------------------------- * (setf cheers '(cheer cheer cheer)) * (setf loop-count 0) * (loop (when (endp cheers) (return loop-count)) (setf cheers (rest cheers)) (setf loop-count (+ loop-count 1))) 3 ------------------------------------------------------------------- * (prog1 (setf a 'x) (setf b 'y) (setf c 'z)) X * (progn (setf a 'x) (setf b 'y) (setf c 'z)) Z ---------------------------------------------------------------------- (if <test> (progn <nonNIL side effect> ... <nonNIL consequent>) (progn <NIL side effect> ... <NIL consequent>)) 解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解 7-1: (defun do-times-factorial (n) (let ((result 1)) (dotimes (count n result) (setf result (* (+ 1 count) result))))) Note that this version of DOTIMES-FACTORIAL is somewhat inefficient because we have to add one to COUNT each time the body of the DOTIMES form is evaluated. If we did not do this, N would range from 0 to n-1 rather than from 1 to n. ---------------------------------------------------------------- 7-2: (defun count-outlyers-with-count-if (list-of-element) (count-if #'(lambda (element) (or (> element boiling) (< element freezing))) list-of elements)) ----------------------------------------------------------------- 7-3: (defun list-outlyers (list-of-elements) (let ((outlyers nil)) ;Initialize result. (dolist (element list-of-elements ;Establish DOLIST parameter. outlyers) ;Return form. (when (or (> element boiling) ;Test element against high. (< element freezing)) ;Test element against low. (setf outlyers ;Add element to the result. (cons element outlyers)))))) ;Build result. ------------------------------------------------------------------- 7-4: (defun list-outlyer-counts (list-of-elements) (let ((count-above 0) ;Initialize count parameter. (count-below 0)) ;Initialize count parameter. (dolist (element list-of-elements ;Establish DOLIST parameter. (list count-below count-above)) ;Return form. (cond ((> element boiling) ;Test element against high. (setf count-above ;Increment COUNT-ABOVE. (+ count-above 1))) ((< element freezing) ;Test element against low. (setf count-below ;Increment count-BELOW. (+ count-below 1)))))) -------------------------------------------------------------------- 7-5: (defun dolist-member (item initial-list) (dolist (l initial-list) ;Step through all elements. (when (eql item l) (return t)))) -------------------------------------------------------------------- 7-6: (defun dolist-reverse (initial-list) (let ((result nil)) (dolist (l initial-list result) ;Step through all elements. (setf result (cons l result))))) ;Build result using CONS. --------------------------------------------------------------------- 7-7: (defun do-factorial (n) (do ((result 1 (* n result)) ;Initialize and reset. (n n (- n 1))) ;Initialize and reset. ((zerop n) result))) ;Test and return. ------------------------------------------------------------------ 7-8: (defun do-member (item initial-list) (do ((l initial-list (rest l))) ;Step through all elements. ((or (endp l) ;List exhausted? (eql item (first l))) ;First element EQL to ITEM? l))) ;Return L, which may be NIL. ------------------------------------------------------------------- 7-9: (defun do-reverse (initial-list) (do ((l initial-list (rest l)) ;Step through elements. (result nil (cons (first l) result))) ;Build Result. ((endp l) result))) ;Terminate.