This is a simple LISP program to read in three sides of a triangle and report what kind of triangle it is (or isn't). Any feedback would be much appreciated.
(defun read-side (side) (format t "Enter a value for side ~d: ~%" side) (read))
(defun is-a-triangle (a b c) (if (and (< a (+ b c)) (< b (+ a c)) (< c (+ a b))) t nil))
(defun is-equilateral (a b c) (if (and (= a b c)) t nil))
(defun is-isoceles (a b c) (if (or (= a b) (= b c)) t nil))
(defun is-right-triangle (a b c)
(let ((square-of-short-sides-sum 0) (short-sides ()) (large-side 0) (sides (list a b c)))
(loop for p in sides do
(if (> p large-side)
(progn (if (/= 0 large-side) (setq short-sides (append short-sides (list large-side))))
(setq large-side p))
(setq short-sides (append short-sides (list p)))))
(format t "short-sides: ~a ~%" short-sides)
(format t "large-side: ~a ~%" large-side)
(loop for p in short-sides do
(setq square-of-short-sides-sum (+ square-of-short-sides-sum (expt p 2))))
(if (= (expt large-side 2) square-of-short-sides-sum) t nil)))
(defun status-message (message a b c) (format t "The shape ~d,~d,~d ~a ~%" a b c message))
(let ((a (read-side 1)) (b (read-side 2)) (c (read-side 3)))
(status-message "is being checked..." a b c)
(if (is-equilateral a b c) (status-message "is an equilateral triangle." a b c)
(if (is-a-triangle a b c)
(progn (if (is-isoceles a b c) (status-message "is an isoceles triangle." a b c)
(if (is-right-triangle a b c) (status-message "is a right triangle." a b c)
(status-message "is a non-isoceles, non-equilateral, non-right triangle." a b c))))
(status-message "is not a triangle." a b c))))
Thanks to the previous commenters for your suggestions. I have since modified the code based on the feedback I have received and am posting the revised code below. If you have any further feedback on this new revision, it is welcome. Thank you!
(defun read-side (side) (format t "Enter a value for side ~d: ~%" side) (read))
(defun triangle-p (a b c) (and (< a (+ b c)) (< b (+ a c)) (< c (+ a b))))
(defun equilateral-p (a b c) (= a b c))
(defun isoceles-p (a b c) (or (= a b) (= b c)))
(defun right-triangle-p (a b c)
(destructuring-bind (long-side &rest short-sides) (sort (list a b c) #'>)
(= (expt long-side 2) (+ (expt (first short-sides) 2) (expt (second short-sides) 2)))))
(defun status-message (message a b c) (format t "The shape ~d,~d,~d ~a ~%" a b c message))
(defun classify-triangle (a b c)
(cond ((not (triangle-p a b c)))
((right-triangle-p a b c) 'right)
((equilateral-p a b c) 'equilateral)
((isoceles-p a b c) 'isoceles)
(t 'triangle)))
(let (triangle-type (a (read-side 1)) (b (read-side 2)) (c (read-side 3)))
(format t "classify triangle says ~a ~%" (classify-triangle a b c))
(setq triangle-type (classify-triangle a b c))
(cond ((eq 'right triangle-type) (status-message "is a right triangle." a b c))
((eq 'equilateral triangle-type) (status-message "is an equilateral triangle." a b c))
((eq 'isoceles triangle-type) (status-message "is an isoceles triangle." a b c))
((eq 'triangle triangle-type) (status-message "is a non-right, non-isoceles, non-equilateral triangle." a b c))
(t (status-message "is not a triangle." a b c))))
Here is the latest revision:
(defun read-side (side) (format t "Enter a value for side ~d: ~%" side) (read))
(defun triangle-p (a b c) (and (< a (+ b c)) (< b (+ a c)) (< c (+ a b))))
(defun equilateral-p (a b c) (= a b c))
(defun isoceles-p (a b c) (or (= a b) (= b c)))
(defun right-triangle-p (a b c)
(destructuring-bind (long-side &rest short-sides) (sort (list a b c) #'>)
(= (expt long-side 2) (+ (expt (first short-sides) 2) (expt (second short-sides) 2)))))
(defun status-message (message a b c) (format t "The shape ~d,~d,~d ~a ~%" a b c message))
(defun classify-triangle (a b c)
(cond ((not (triangle-p a b c)))
((right-triangle-p a b c) 'right)
((equilateral-p a b c) 'equilateral)
((isoceles-p a b c) 'isoceles)
(t 'triangle)))
(let* ((a (read-side 1)) (b (read-side 2)) (c (read-side 3)) (triangle-type (classify-triangle a b c)))
(format t "classify triangle says ~a ~%" triangle-type)
(cond ((eq 'right triangle-type) (status-message "is a right triangle." a b c))
((eq 'equilateral triangle-type) (status-message "is an equilateral triangle." a b c))
((eq 'isoceles triangle-type) (status-message "is an isoceles triangle." a b c))
((eq 'triangle triangle-type) (status-message "is a non-right, non-isoceles, non-equilateral triangle." a b c))
(t (status-message "is not a triangle." a b c))))
After reading through your suggestion on my sorting question and then reading up on 'format', I tried to write a format statement to simplify the logic at the bottom of the code. I couldn't figure out how to do a format conditional based on a symbol, so instead I defined the triangle types as global variables with 'defineparameter' (is there a better way to define constants?). I also used the format loop which you described in your response to the my-sort-3 question to shorten the expression. The new code is as follows:
(defparameter *right* 0)
(defparameter *equilateral* 1)
(defparameter *isoceles* 2)
(defparameter *triangle* 3)
(defparameter *non-triangle* 4)
(defun read-side (side) (format t "Enter a value for side ~d: ~%" side) (read))
(defun triangle-p (a b c) (and (< a (+ b c)) (< b (+ a c)) (< c (+ a b))))
(defun equilateral-p (a b c) (= a b c))
(defun isoceles-p (a b c) (or (= a b) (= b c) (= a c)))
(defun right-triangle-p (a b c)
(destructuring-bind (long-side &rest short-sides) (sort (list a b c) #'>)
(= (expt long-side 2) (+ (expt (first short-sides) 2) (expt (second short-sides) 2)))))
(defun status-message (message a b c) (format t "The shape ~d,~d,~d ~a ~%" a b c message))
(defun classify-triangle (a b c)
(cond ((not (triangle-p a b c)) *non-triangle*)
((right-triangle-p a b c) *right*)
((equilateral-p a b c) *equilateral*)
((isoceles-p a b c) *isoceles*)
(t *triangle*)))
(let* ((a (read-side 1)) (b (read-side 2)) (c (read-side 3)) (triangle-type (classify-triangle a b c)))
(format t "classify triangle says ~a ~%" triangle-type)
(format t "The shape (~{~d~^, ~}) is ~[a right~;an equilateral~;an isoceles~;a non-right, non-isoceles, non-equilateral~;not a~] triangle." (list a b c) triangle-type))
Thanks, everyone, for your continued feedback. Here is the latest revision.
(defun read-side (side) (format t "Enter a value for side ~d: ~%" side) (read))
(defun triangle-p (a b c) (and (< a (+ b c)) (< b (+ a c)) (< c (+ a b))))
(defun equilateral-p (a b c) (= a b c))
(defun isoceles-p (a b c) (or (= a b) (= b c)))
(defun right-triangle-p (a b c)
(destructuring-bind (long-side short-side-1 short-side-2) (sort (list a b c) #'>)
(= (expt long-side 2) (+ (expt short-side-1 2) (expt short-side-2 2)))))
(defun status-message (message a b c) (format t "The shape ~d,~d,~d ~a ~%" a b c message))
(defun classify-triangle (a b c)
(cond ((not (triangle-p a b c)) nil)
((right-triangle-p a b c) 'right)
((equilateral-p a b c) 'equilateral)
((isoceles-p a b c) 'isoceles)
(t 'triangle)))
(let* ((a (read-side 1)) (b (read-side 2)) (c (read-side 3))
(triangle-type (classify-triangle a b c))
(article (if (member triangle-type '(isoceles equilateral)) "an" "a"))
(tri-name (if (eq triangle-type 'triangle) "non-right, non-isoceles, non-equilateral" triangle-type)))
(format t "The shape (~d, ~d, ~d) is ~:[not a triangle~;~a ~(~a~) triangle~]." a b c triangle-type article tri-name))