ANSI Common Lisp: 4 Specialized Data Structures June 16, 2003 4.1 Define a function to take a square array (an array whose dimensions are ( n, n ) ) and rotate it 90 clockwise: > (quarter-turn #2A((a b) (c d))) #2A((C A) (D B)) You’ll need array-dimensions (page 361). Solution: (defun quarter-turn (arr) (let* ((dim (array-dimensions arr)) ; dimensions of original array (row (first dim)) ; row # of original array (col (second dim)) ; column # of original array (n row) ; dimension of original array new-arr) (cond ((not (= row col)) ; check if original array is a square one (format t "The argument is not a square array.~%")) (t (setf new-arr (make-array dim :initial-element nil)) (do ((i 0 (+ i 1))) ((= i n)) (do ((j 0 (+ j 1))) ((= j n)) (setf (aref new-arr j i) (aref arr (- n i 1) j)))) new-arr)))) (quarter-turn #2A((a b) (c d))) #2A((C A) (D B)) (quarter-turn #2A((a b c) (d e f) (g h i))) #2A((G D A) (H E B) (I F C)) 4.2 Read the description of reduce on page 368, then use it to define: (a) copy-list (b) reverse (for lists) Solution: 1/4 (defun reduce-copy-list (lst) (reduce #'(lambda (x y) (append x (list y))) lst :initial-value ())) (defun reduce-reverse (lst) (reduce #'(lambda (x y) (append y (list x))) lst :from-end t :initial-value)) (reduce-copy-list '(1 2 (5 6) 3 4)) (1 2 (5 6) 3 4) (reduce-reverse '(1 2 (5 6) 3 4)) (4 3 (5 6) 2 1) 4.3 Define a structure to represent a tree where each node contains some data and has up to three children. Define (a) a function to copy such a tree (so that no node in the copy is eql to a node in the original) (b) a function that takes an object and such a tree, and returns true if the object is eql to the data field of one of the nodes Solution: (defstruct (node (:print-function (lambda (n s d) (format s "#<~A,~A>" (node-elt1 n) (node-elt2 n))))) elt1 elt2 (l nil) (m nil) (r nil)) (defun tree-copy (tree) (if (not (null tree)) (let ((elt1 (node-elt1 (elt2 (node-elt2 (make-node :elt1 elt1 :elt2 elt2 :l (tree-copy (node-l :m (tree-copy (node-m :r (tree-copy (node-r tree)) tree))) tree)) tree)) tree)))))) (defun tree-find (obj tree) (when tree (if (not (tree-find obj (node-l tree))) (if (or (eql obj (node-elt1 tree)) (eql obj (node-elt2 tree))) t (if (not (tree-find obj (node-m tree))) (if (or (eql obj (node-elt1 tree)) (eql obj (node-elt2 tree))) 2/4 t (if (not (tree-find obj (node-r tree))) (if (or (eql obj (node-elt1 tree)) (eql obj (nodeelt2 tree))) t)))))))) 4.4 Define a function that takes a BST and returns a list of its elements ordered from greatest to least. Solution: (defun reverse-order (bst) (reverse-order-recur '() bst)) (defun reverse-order-recur (lst bst) (when bst (setf lst (reverse-order lst (node-r bst))) (setf lst (append lst (list (node-elt bst)))) (setf lst (reverse-order lst (node-l bst)))) lst) (reverse-order nums) (9 8 7 6 5 4 3 2 1) 4.5 Define bst-adjoin. This function should take the same arguments as bst-insert, but should only insert the object if there is nothing eql to it in the tree. Solution: (defun bst-adjoin (obj bst <) (if (not (bst-find obj bst #'<)) (bst-insert obj bst #'<))) 4.6 The contents of any hash table can be described by an assoc-list whose elements are (k . v), for each key-value pair in the hash table. Define a function that (a) takes an assoc-list and returns a corresponding hash table. (b) takes a hash table and returns a corresponding assoc-list Solution: (defun alist-hashtable (lst) (let ((ht (make-hash-table))) (dolist (item lst) 3/4 (setf (gethash (car item) ht) (cdr item))) ht)) (defun hashtable-alist (ht) (let ((alist '())) (maphash #'(lambda (key value) (setf alist (append alist (list (cons key value))))) ht) alist)) 4/4