I've solved an assignment a week ago, which is my first assignment using Lisp.
Tasks:
Task 1:
a. Given a tree as recursive lists, print the tree in breadth first order.
b. Given a tree like in task 1a, print it in child-successor order.
Input for Tasks 1a and 1b:
(A (B (C (D))(E (F) (G (H)))) (J (K (L (M) (N (P))))))
Output for Task 1a:
A B J C E K D F G L H M N P
Output for Task 1b:
A, B J B, C E J, K C, D E, F G K, L D, F, G, H L, M N H, M, N, P P,
Task 2:
Tasks 2a and 2b are the same as in task 1, but now the nodes of the tree have costs. The cost represents the cost from the node parent to this node. When printing, cost should be accumulated starting from the root (2a, 2b are using styles defined by 1a, 1b accordingly).
Input for Task 2:
((A 0) ((B 5) ((C 3) ((D 4))) ((E 2) ((F 1)) ((G 7) ((H 9))))) ((J 1) ((K 3) ((L 1) ((M 7)) ((N 1) ((P 2)))))))
Output for Task 2a:
B,5 J,1 C,8 E,7 K,4 D,12 F,8 G,14 L,5 H,23 M,12 N,6 P,8
Output for Task 2b:
A,0; B,5 J,1 B,5; C,3 E,2 J,1; K,3 C,8; D,4 E,7; F,1 G,7 K,4; L,1 D,12; F,8; G,14 H,9 L,5; M,7 N,1 H,23; M,12; N,6; P,2 P,8;
Solution
I implemented my solution using an iterative approach - taking and printing cdr's of each childs (tasks are marked using comments):
;; Task 1a ;; This function takes a list of lists and ;; prints (car) for every sublist then repeats ;; for accumulated (cdr)'s of those sublists if not empty (defun breadth-print (node) (loop while (not (eq nil node)) do (setq temp nil) (loop for i in node do (progn (format t "~a " (car i)) (mapcar #'(lambda (j) (if (null temp) (setq temp (list j)) (setq temp (append temp (list j))))) (cdr i)))) (setq node temp) (format t "~%"))) ;; Task 1b ;; This function utilizes the same principle ;; as breadth-print, however each node is printed ;; on a new line with its children (defun breadth-print-childs (node) (loop while (not (eq nil node)) do (setq temp nil) (loop for i in node do (progn (format t "~a, " (car i)) (loop for beta in (cdr i) do (format t "~d " (car beta))) (format t "~%") (mapcar #'(lambda (j) (if (null temp) (setq temp (list j)) (setq temp (append temp (list j))))) (cdr i)))) (setq node temp))) ;; Task 2a ;; This function is based on breadth-print and ;; the only difference is that the costs are ;; updated for every element in (cdr) of sublists, ;; and formatting is a bit different (defun breadth-print-costs (node) (loop while (not (eq nil node)) do (setq temp nil) (loop for i in node do (progn (format t "~{~a,~a~} " (car i)) (mapcar #'(lambda (j) (progn (setf (nth 1 (car j)) (+ (nth 1 (car j)) (nth 1 (car i)))) (if (null temp) (setq temp (list j)) (setq temp (append temp (list j)))))) (cdr i)))) (setq node temp) (format t "~%"))) ;; Task 2b ;; This function utilizes the same principle ;; as breadth-print-childs, with only addition ;; is the calclulations of cost (similar fasion is used in breadth-print-costs), ;; which is modified according to the already passed path (defun breadth-print-childs-costs (node) (loop while (not (eq nil node)) do (setq temp nil) (loop for i in node do (progn (format t "~{~a,~a~}; " (car i)) (loop for beta in (cdr i) do (format t "~{~a,~a~} " (car beta))) (format t "~%") (mapcar #'(lambda (j) (progn (setf (nth 1 (car j)) (+ (nth 1 (car j)) (nth 1 (car i)))) (if (null temp) (setq temp (list j)) (setq temp (append temp (list j)))))) (cdr i)))) (setq node temp))) (format t "Task 1a provide input: ") (defparameter *inpa* (list (read))) (format t "~%Input 1a is ~a~%Part 1a:~%" *inpa*) (breadth-print *inpa*) (format t "Task 1b provide input: ") (defparameter *inpb* (list (read))) (format t "~%Input 1b is ~a~%Part 1b:~%" *inpb*) (breadth-print-childs *inpb*) (format t "Task 2a provide input: ") (defparameter *inpc* (list (read))) (format t "~%Input 2a is ~a~%Part 2a:~%" *inpc*) (breadth-print-costs *inpc*) (format t "Task 2b provide input: ") (defparameter *inpd* (list (read))) (format t "Input 2b is ~a~%Part 2b:~%" *inpd*) (breadth-print-childs-costs *inpd*)
Concerns
What I would like to improve:
- Does it fit the Lisp coding style?
- Performance (is my iterative approach viable?)
- Function choice and general structure of the code (I'm sure that there should be a better way to do the temp checks or completely avoid them)