diff --git a/koans-solved/control-statements.lisp b/koans-solved/control-statements.lisp index a5952854..796ca86b 100644 --- a/koans-solved/control-statements.lisp +++ b/koans-solved/control-statements.lisp @@ -14,18 +14,18 @@ (define-test if ;; IF only evaluates and returns one branch of a conditional expression. - (assert-equal ____ (if t :true :false)) - (assert-equal ____ (if nil :true :false)) + (assert-equal :true (if t :true :false)) + (assert-equal :false (if nil :true :false)) ;; This also applies to side effects that migh or might not be evaluated. (let ((result)) (if t (setf result :true) (setf result :false)) - (assert-equal ____ result) + (assert-equal :true result) (if nil (setf result :true) (setf result :false)) - (assert-equal ____ result))) + (assert-equal :false result))) (define-test when-unless ;; WHEN and UNLESS are like one-branched IF statements. @@ -40,29 +40,29 @@ (unless (> x 5) (setf unless-result x) (push x unless-numbers))) - (assert-equal ____ when-result) - (assert-equal ____ when-numbers) - (assert-equal ____ unless-result) - (assert-equal ____ unless-numbers))) + (assert-equal 10 when-result) + (assert-equal '(10 9 8 7 6) when-numbers) + (assert-equal 5 unless-result) + (assert-equal '(5 4 3 2 1) unless-numbers))) (define-test and-short-circuit ;; AND only evaluates forms until one evaluates to NIL. - (assert-equal ____ + (assert-equal 5 (let ((x 0)) (and - (setf x (+ 1 x)) - (setf x (+ 1 x)) + (setf x (+ 2 x)) + (setf x (+ 3 x)) nil - (setf x (+ 1 x))) + (setf x (+ 4 x))) x))) (define-test or-short-circuit ;; AND only evaluates forms until one evaluates to non-NIL. - (assert-equal ____ + (assert-equal 2 (let ((x 0)) (or - (setf x (+ 1 x)) - (setf x (+ 1 x)) + (setf x (+ 2 x)) + (setf x (+ 3 x)) nil - (setf x (+ 1 x))) + (setf x (+ 4 x))) x))) diff --git a/koans-solved/iteration.lisp b/koans-solved/iteration.lisp index e820bc51..65338f4c 100644 --- a/koans-solved/iteration.lisp +++ b/koans-solved/iteration.lisp @@ -22,11 +22,11 @@ (dolist (number numbers) ;; (INCF PLACE N) is equivalent to (SETF PLACE (+ N PLACE)). (incf sum number)) - (assert-equal ____ sum)) + (assert-equal 108 sum)) ;; DOLIST can optionally return a value. (let ((sum 0)) - (assert-equal ____ (dolist (number numbers sum) - (incf sum number)))))) + (assert-equal 108 (dolist (number numbers sum) + (incf sum number)))))) (define-test dotimes ;; The macro DOTIMES binds a variable to subsequent integers from 0 to @@ -34,11 +34,11 @@ (let ((stack '())) (dotimes (i 5) (push i stack)) - (assert-equal ____ stack)) + (assert-equal '(4 3 2 1 0) stack)) ;; DOTIMES can optionally return a value. (let ((stack '())) - (assert-equal ____ (dotimes (i 5 stack) - (push i stack))))) + (assert-equal '(4 3 2 1 0) (dotimes (i 5 stack) + (push i stack))))) (define-test do ;; The macro DO accepts a list of variable bindings, a termination test with @@ -47,7 +47,7 @@ (do ((i 0 (1+ i))) ((> i 5)) (push i result)) - (assert-equal ____ result)) + (assert-equal '(0 1 2 3 4 5) (nreverse result))) ;; The epilogue of DO can return a value. (let ((result (do ((i 0 (1+ i)) ;; A variable bound by DO noes not need to be updated on @@ -55,7 +55,7 @@ (result '())) ((> i 5) (nreverse result)) (push i result)))) - (assert-equal ____ result))) + (assert-equal '(0 1 2 3 4 5) result))) (define-test loop-basic-form ;; The macro LOOP in its simple form loops forever. It is possible to stop the @@ -64,10 +64,10 @@ (loop (incf counter) (when (>= counter 100) (return counter))) - (assert-equal ___ loop-counter)) + (assert-equal 100 counter)) ;; The RETURN special form can return a value out of a LOOP. - (let ((loop-counter 0)) - (assert-equal ___ (loop (incf counter) + (let ((counter 0)) + (assert-equal 100 (loop (incf counter) (when (>= counter 100) (return counter))))) ;; The extended form of LOOP will be contemplated in a future koan. diff --git a/koans-solved/loops.lisp b/koans-solved/loops.lisp index 85429bdd..9b55c903 100644 --- a/koans-solved/loops.lisp +++ b/koans-solved/loops.lisp @@ -20,9 +20,9 @@ (let* ((result-1 (loop for letter in '(#\a \b #\c #\d) collect letter)) (result-2 (loop for number in '(1 2 3 4 5) sum number)) (result-3 (loop for list in '((foo) (bar) (baz)) append list))) - (assert-equal ____ result-1) - (assert-equal ____ result-2) - (assert-equal ____ result-3))) + (assert-equal '(#\a \b #\c #\d) result-1) + (assert-equal 15 result-2) + (assert-equal '(foo bar baz) result-3))) (define-test loop-multiple-variables ;; With multiple FOR clauses, the loop ends when any of the provided lists are @@ -31,7 +31,7 @@ (result (loop for letter in letters for i from 1 to 1000 collect (list i letter)))) - (assert-equal ____ result))) + (assert-equal '((1 :a) (2 :b) (3 :c) (4 :d)) result))) (define-test loop-in-versus-loop-on ;; Instead of iterating over each element of a list, we can iterate over each @@ -39,18 +39,18 @@ (let* ((letters '(:a :b :c)) (result-in (loop for thing in letters collect thing)) (result-on (loop for thing on letters collect thing))) - (assert-equal ____ result-in) - (assert-equal ____ result-on))) + (assert-equal '(:a :b :c) result-in) + (assert-equal '((:a :b :c) (:b :c) (:c)) result-on))) (define-test loop-for-by ;; Numeric iteration can go faster or slower if we use the BY keyword. (let* ((result (loop for i from 0 to 30 by 5 collect i))) - (assert-equal ____ result))) + (assert-equal '(0 5 10 15 20 25 30) result))) (define-test loop-counting-backwards ;; We can count downwards instead of upwards by using DOWNTO instead of TO. (let ((result (loop for i from 5 downto -5 collect i))) - (assert-equal ____ result))) + (assert-equal '(5 4 3 2 1 0 -1 -2 -3 -4 -5) result))) (define-test loop-list-by ;; List iteration can go faster or slower if we use the BY keyword. @@ -59,31 +59,31 @@ (result-cdr (loop for letter in letters by #'cdr collect letter)) (result-cddr (loop for letter in letters by #'cddr collect letter)) (result-cdddr (loop for letter in letters by #'cdddr collect letter))) - (assert-equal ____ result-in) - (assert-equal ____ result-in-cdr) - (assert-equal ____ result-in-cddr) - (assert-equal ____ result-in-cdddr))) + (assert-equal '(:a :b :c :d :e :f) result) + (assert-equal '(:a :b :c :d :e :f) result-cdr) + (assert-equal '(:a :c :e) result-cddr) + (assert-equal '(:a :d) result-cdddr))) (define-test loop-across ;; LOOP can iterate over a vector with the ACROSS keyword. (let* ((vector (make-array '(5) :initial-contents '(0 1 2 3 4))) (result (loop for number across vector collect number))) - (assert-equal ____ result))) + (assert-equal '(0 1 2 3 4) result))) (define-test loop-over-2d-array (let ((array (make-array '(3 2) :initial-contents '((0 1) (2 3) (4 5))))) ;; LOOP can be combined with ROW-MAJOR-AREF to iterate over the contents of ;; a multidimensional array. (let* ((result (loop for i from 0 below (array-total-size array) - collect (row-major-aref my-array i)))) - (assert-equal ____ result)) + collect (row-major-aref array i)))) + (assert-equal '(0 1 2 3 4 5) result)) ;; It is always possible to resort to nested loops. (let* ((result (loop with max-i = (array-dimension array 0) for i from 0 below max-i collect (loop with max-j = (array-dimension array 1) for j from 0 below max-j - collect (expt (aref my-array i j) 2))))) - (assert-equal ____ result)))) + collect (expt (aref array i j) 2))))) + (assert-equal '((0 1) (4 9) (16 25)) result)))) (define-test loop-hash-table (let ((book-heroes (make-hash-table :test 'equal))) @@ -92,12 +92,12 @@ (gethash "The Wizard Of Oz" book-heroes) "Dorothy" (gethash "The Great Gatsby" book-heroes) "James Gatz") ;; LOOP can iterate over hash tables. - (let (pairs-in-table (loop for key being the hash-key of book-heroes - using (hash-value value) - collect (list key value))) - (assert-equal ____ (length pairs-in-table)) - (true-or-false? ____ (find '("The Hobbit" "Bilbo") pairs-in-table - :test #'equal))))) + (let ((pairs-in-table (loop for key being the hash-key of book-heroes + using (hash-value value) + collect (list key value)))) + (assert-equal 4 (length pairs-in-table)) + (true-or-false? t (find '("The Hobbit" "Bilbo") pairs-in-table + :test #'equal))))) (define-test loop-statistics ;; LOOP can perform basics statistics on the collected elements. @@ -110,11 +110,11 @@ finally (return (list collected counted summed maximized minimized))))) (destructuring-bind (collected counted summed maximized minimized) result - (assert-equal ____ collected) - (assert-equal ____ counted) - (assert-equal ____ summed) - (assert-equal ____ maximized) - (assert-equal ____ minimized)))) + (assert-equal '(1 2 4 8 16 32) collected) + (assert-equal 6 counted) + (assert-equal 63 summed) + (assert-equal 32 maximized) + (assert-equal 1 minimized)))) (define-test loop-destructuring ;; LOOP can bind multiple variables on each iteration step. @@ -122,19 +122,19 @@ (result (loop for (a b) in '((1 9) (2 8) (3 7) (4 6)) do (incf count) collect (+ a b)))) - (assert-equal ____ count) - (assert-equal ____ result))) + (assert-equal 4 count) + (assert-equal '(10 10 10 10) result))) -(define-test conditional-execution +(define-test loop-conditional-execution (let ((numbers '(1 1 2 3 5 8 13 21))) ;; LOOP can execute some actions conditionally. (let ((result (loop for x in numbers when (evenp x) sum x))) - (assert-equal ____ result)) + (assert-equal 10 result)) (let ((result (loop for x in numbers unless (evenp x) sum x))) - (assert-equal ____ result)) + (assert-equal 44 result)) (flet ((greater-than-10-p (x) (> x 10))) (let ((result (loop for x in numbers - when (greater-than-10-p 10) sum x))) - (assert-equal ____ result))))) + when (greater-than-10-p x) sum x))) + (assert-equal 34 result))))) diff --git a/koans-solved/mapcar-and-reduce.lisp b/koans-solved/mapcar-and-reduce.lisp index 4df282a6..57743479 100644 --- a/koans-solved/mapcar-and-reduce.lisp +++ b/koans-solved/mapcar-and-reduce.lisp @@ -19,79 +19,84 @@ ;; Inside MAPCAR, he function 1+ will be applied to each element of NUMBERS. ;; A new list will be collected from the results. (assert-equal '(2 3 4 5 6 7) (mapcar #'1+ numbers)) - (assert-equal ____ (mapcar #'- numbers)) - (assert-equal ____ (mapcar #'list numbers)) - (assert-equal ____ (mapcar #'evenp numbers)) - (assert-equal ____ (mapcar #'numberp numbers)) - (assert-equal ____ (mapcar #'stringp numbers)) + (assert-equal '(-1 -2 -3 -4 -5 -6) (mapcar #'- numbers)) + (assert-equal '((1) (2) (3) (4) (5) (6)) (mapcar #'list numbers)) + (assert-equal '(nil t nil t nil t) (mapcar #'evenp numbers)) + (assert-equal '(t t t t t t) (mapcar #'numberp numbers)) + (assert-equal '(nil nil nil nil nil nil) (mapcar #'stringp numbers)) ;; MAPCAR can work on multiple lists. The function will receive one argument ;; from each list. - (let (other-numbers '(4 8 15 16 23 42)) - (assert-equal ____ (mapcar #'+ numbers other-numbers)) - (assert-equal ____ (mapcar #'* numbers other-numbers)) + (let ((other-numbers '(4 8 15 16 23 42))) + (assert-equal '(5 10 18 20 28 48) (mapcar #'+ numbers other-numbers)) + (assert-equal '(4 16 45 64 115 252) (mapcar #'* numbers other-numbers)) ;; The function MOD performs modulo division. - (assert-equal ____ (mapcar #'mod other-numbers numbers))))) + (assert-equal '(0 0 0 0 3 0) (mapcar #'mod other-numbers numbers))))) (define-test mapcar-lambda ;; MAPCAR is often used with anonymous functions. (let ((numbers '(8 21 152 37 403 14 7 -34))) - (assert-equal ____ (mapcar (lambda (x) (mod x 10)) numbers))) + (assert-equal '(8 1 2 7 3 4 7 6) (mapcar (lambda (x) (mod x 10)) numbers))) (let ((strings '("Mary had a little lamb" "Old McDonald had a farm" "Happy birthday to you"))) - (assert-equal ____ (mapcar (lambda (x) (subseq x 4 12)) strings)))) + (assert-equal '(" had a l" "McDonald" "y birthd") + (mapcar (lambda (x) (subseq x 4 12)) strings)))) (define-test map ;; MAP is a variant of MAPCAR that works on any sequences. ;; It allows to specify the type of the resulting sequence. (let ((string "lorem ipsum")) - (assert-equal ____ (map 'string #'char-upcase string)) - (assert-equal ____ (map 'list #'char-upcase string)) + (assert-equal "LOREM IPSUM" (map 'string #'char-upcase string)) + (assert-equal '(#\L #\O #\R #\E #\M #\Space #\I #\P #\S #\U #\M) + (map 'list #'char-upcase string)) ;; Not all vectors containing characters are strings. - (assert-equal ____ (map '(vector t) #'char-upcase string)))) + (assert-equalp #(#\L #\O #\R #\E #\M #\Space #\I #\P #\S #\U #\M) + (map '(vector t) #'char-upcase string)))) (define-test transposition ;; MAPCAR gives the function as many arguments as there are lists. - (flet ((transpose (lists) (apply #'mapcar ____ lists))) + (flet ((transpose (lists) (apply #'mapcar #'list lists))) (let ((list '((1 2 3) (4 5 6) (7 8 9))) (transposed-list '((1 4 7) (2 5 8) - (3 6 9))))) - (assert-equal transposed-list (transpose list)) - (assert-equal ____ (transpose (transpose list)))) - (assert-equal ____ (transpose '(("these" "making") - ("pretzels" "me") - ("are" "thirsty"))))) + (3 6 9)))) + (assert-equal transposed-list (transpose list)) + (assert-equal list (transpose (transpose list)))) + (assert-equal '(("these" "pretzels" "are") + ("making" "me" "thirsty")) + (transpose '(("these" "making") + ("pretzels" "me") + ("are" "thirsty")))))) (define-test reduce ;; The function REDUCE combines the elements of a list by applying a binary ;; function to the elements of a sequence from left to right. (assert-equal 15 (reduce #'+ '(1 2 3 4 5))) - (assert-equal ____ (reduce #'+ '(1 2 3 4))) - (assert-equal ____ (reduce #'expt '(1 2 3 4 5)))) + (assert-equal 10 (reduce #'+ '(1 2 3 4))) + (assert-equal 1 (reduce #'expt '(1 2 3 4 5)))) (define-test reduce-from-end ;; The :FROM-END keyword argument can be used to reduce from right to left. (let ((numbers '(1 2 3 4 5))) - (assert-equal ____ (reduce #'cons numbers)) - (assert-equal ____ (reduce #'cons numbers :from-end t))) + (assert-equal '((((1 . 2) . 3) . 4) . 5) (reduce #'cons numbers)) + (assert-equal '(1 2 3 4 . 5) (reduce #'cons numbers :from-end t))) (let ((numbers '(2 3 2))) - (assert-equal ____ (reduce #'expt numbers)) - (assert-equal ____ (reduce #'expt numbers :from-end t)))) + (assert-equal 64 (reduce #'expt numbers)) + (assert-equal 512 (reduce #'expt numbers :from-end t)))) (define-test reduce-initial-value ;; :INITIAL-VALUE can supply the initial value for the reduction. (let ((numbers '(1 2 3 4 5))) - (assert-equal ____ (reduce #'* numbers)) - (assert-equal ____ (reduce #'* numbers :initial-value 0)) - (assert-equal ____ (reduce #'* numbers :initial-value -1)))) + (assert-equal 120 (reduce #'* numbers)) + (assert-equal 0 (reduce #'* numbers :initial-value 0)) + (assert-equal -120 (reduce #'* numbers :initial-value -1)))) (define-test inner-product ;; MAPCAR and REDUCE are powerful when used together. ;; Fill in the blanks to produce a local function that computes an inner ;; product of two vectors. - (flet ((inner-product (x y) (reduce ____ (mapcar ____ x y)))) + (flet ((inner-product (x y) (reduce #'+ (mapcar #'* x y)))) (assert-equal 32 (inner-product '(1 2 3) '(4 5 6))) (assert-equal 310 (inner-product '(10 20 30) '(4 3 7))))) diff --git a/koans/control-statements.lisp b/koans/control-statements.lisp index a5952854..04929b67 100644 --- a/koans/control-statements.lisp +++ b/koans/control-statements.lisp @@ -50,10 +50,10 @@ (assert-equal ____ (let ((x 0)) (and - (setf x (+ 1 x)) - (setf x (+ 1 x)) + (setf x (+ 2 x)) + (setf x (+ 3 x)) nil - (setf x (+ 1 x))) + (setf x (+ 4 x))) x))) (define-test or-short-circuit @@ -61,8 +61,8 @@ (assert-equal ____ (let ((x 0)) (or - (setf x (+ 1 x)) - (setf x (+ 1 x)) + (setf x (+ 2 x)) + (setf x (+ 3 x)) nil - (setf x (+ 1 x))) + (setf x (+ 4 x))) x))) diff --git a/koans/iteration.lisp b/koans/iteration.lisp index e820bc51..5268a3b1 100644 --- a/koans/iteration.lisp +++ b/koans/iteration.lisp @@ -64,12 +64,12 @@ (loop (incf counter) (when (>= counter 100) (return counter))) - (assert-equal ___ loop-counter)) + (assert-equal ____ counter)) ;; The RETURN special form can return a value out of a LOOP. - (let ((loop-counter 0)) - (assert-equal ___ (loop (incf counter) - (when (>= counter 100) - (return counter))))) + (let ((counter 0)) + (assert-equal ____ (loop (incf counter) + (when (>= counter 100) + (return counter))))) ;; The extended form of LOOP will be contemplated in a future koan. ) diff --git a/koans/loops.lisp b/koans/loops.lisp index 85429bdd..00fb7b5f 100644 --- a/koans/loops.lisp +++ b/koans/loops.lisp @@ -59,10 +59,10 @@ (result-cdr (loop for letter in letters by #'cdr collect letter)) (result-cddr (loop for letter in letters by #'cddr collect letter)) (result-cdddr (loop for letter in letters by #'cdddr collect letter))) - (assert-equal ____ result-in) - (assert-equal ____ result-in-cdr) - (assert-equal ____ result-in-cddr) - (assert-equal ____ result-in-cdddr))) + (assert-equal ____ result) + (assert-equal ____ result-cdr) + (assert-equal ____ result-cddr) + (assert-equal ____ result-cdddr))) (define-test loop-across ;; LOOP can iterate over a vector with the ACROSS keyword. @@ -75,14 +75,14 @@ ;; LOOP can be combined with ROW-MAJOR-AREF to iterate over the contents of ;; a multidimensional array. (let* ((result (loop for i from 0 below (array-total-size array) - collect (row-major-aref my-array i)))) + collect (row-major-aref array i)))) (assert-equal ____ result)) ;; It is always possible to resort to nested loops. (let* ((result (loop with max-i = (array-dimension array 0) for i from 0 below max-i collect (loop with max-j = (array-dimension array 1) for j from 0 below max-j - collect (expt (aref my-array i j) 2))))) + collect (expt (aref array i j) 2))))) (assert-equal ____ result)))) (define-test loop-hash-table @@ -92,9 +92,9 @@ (gethash "The Wizard Of Oz" book-heroes) "Dorothy" (gethash "The Great Gatsby" book-heroes) "James Gatz") ;; LOOP can iterate over hash tables. - (let (pairs-in-table (loop for key being the hash-key of book-heroes - using (hash-value value) - collect (list key value))) + (let ((pairs-in-table (loop for key being the hash-key of book-heroes + using (hash-value value) + collect (list key value)))) (assert-equal ____ (length pairs-in-table)) (true-or-false? ____ (find '("The Hobbit" "Bilbo") pairs-in-table :test #'equal))))) @@ -125,7 +125,7 @@ (assert-equal ____ count) (assert-equal ____ result))) -(define-test conditional-execution +(define-test loop-conditional-execution (let ((numbers '(1 1 2 3 5 8 13 21))) ;; LOOP can execute some actions conditionally. (let ((result (loop for x in numbers @@ -136,5 +136,5 @@ (assert-equal ____ result)) (flet ((greater-than-10-p (x) (> x 10))) (let ((result (loop for x in numbers - when (greater-than-10-p 10) sum x))) + when (greater-than-10-p x) sum x))) (assert-equal ____ result))))) diff --git a/koans/mapcar-and-reduce.lisp b/koans/mapcar-and-reduce.lisp index 4df282a6..76dfa830 100644 --- a/koans/mapcar-and-reduce.lisp +++ b/koans/mapcar-and-reduce.lisp @@ -26,7 +26,7 @@ (assert-equal ____ (mapcar #'stringp numbers)) ;; MAPCAR can work on multiple lists. The function will receive one argument ;; from each list. - (let (other-numbers '(4 8 15 16 23 42)) + (let ((other-numbers '(4 8 15 16 23 42))) (assert-equal ____ (mapcar #'+ numbers other-numbers)) (assert-equal ____ (mapcar #'* numbers other-numbers)) ;; The function MOD performs modulo division. @@ -48,7 +48,7 @@ (assert-equal ____ (map 'string #'char-upcase string)) (assert-equal ____ (map 'list #'char-upcase string)) ;; Not all vectors containing characters are strings. - (assert-equal ____ (map '(vector t) #'char-upcase string)))) + (assert-equalp ____ (map '(vector t) #'char-upcase string)))) (define-test transposition ;; MAPCAR gives the function as many arguments as there are lists. @@ -58,12 +58,12 @@ (7 8 9))) (transposed-list '((1 4 7) (2 5 8) - (3 6 9))))) - (assert-equal transposed-list (transpose list)) - (assert-equal ____ (transpose (transpose list)))) - (assert-equal ____ (transpose '(("these" "making") - ("pretzels" "me") - ("are" "thirsty"))))) + (3 6 9)))) + (assert-equal transposed-list (transpose list)) + (assert-equal ____ (transpose (transpose list)))) + (assert-equal ____ (transpose '(("these" "making") + ("pretzels" "me") + ("are" "thirsty")))))) (define-test reduce ;; The function REDUCE combines the elements of a list by applying a binary diff --git a/koans/scoring-project.lisp b/koans/scoring-project.lisp index 33aea48a..9e2e35d8 100644 --- a/koans/scoring-project.lisp +++ b/koans/scoring-project.lisp @@ -50,7 +50,7 @@ ;;; Your goal is to write the scoring function for Greed. (defun score (&rest dice) - ____) + ) (define-test score-of-an-empty-list-is-zero (assert-equal 0 (score))) diff --git a/lisp-koans.lisp b/lisp-koans.lisp index ce8300d4..58224003 100644 --- a/lisp-koans.lisp +++ b/lisp-koans.lisp @@ -90,7 +90,7 @@ (t (format nil "Last koan status: ~A." koan-status)))) (defun print-next-suggestion-message (dirname) - (let ((filename (caar *collected-results*)) + (let ((filename (caar (last *collected-results*))) (koan-name (caaadr (car (last (last *collected-results*))))) (koan-status (reverse (cadaar (cdar (last (last *collected-results*))))))) (format t "~&You have not yet reached enlightenment.