Reputation: 137
I have this small program that prints triangles either forwards or backwards depending on whether the input is positive or negative. It works perfectly, except at the end of every loop it prints NIL. I tried changing the bounds of the loop, but every when I do it effects the size of the triangle. Is there any solution to this? Please find the code below.
(defun triangle(k)
(cond ((or(not(integerp k)) (= k 0)) '("invalid number; please enter a positive or a negative integer"))
((< k -1)
(loop for x from k to -1 do
(loop for y from k to -1 do
(if (< y x)
(princ #\Space)
(princ '*)
)
)
(terpri)
)
)
((or (= k 1) (= k -1)) '*)
(t(loop for x from 0 to k do
(loop for y from 0 to k do
(if (< x y)
(princ '*)
)
)
(terpri)
)
)
)
)
Upvotes: 0
Views: 314
Reputation: 17859
I know that it is off topic, considering your question was about loops, but i would propose to separate data generation, manipulation and representation, which is always a good practice. You could make a single triangle generator, and then invert it, if needed. It could look like this, for example:
(defun mk-tri (n)
(when (plusp n)
(loop for i from 1 to n
collect (nconc (loop repeat i collect #\*)
(loop repeat (- n i) collect #\space)))))
(defun print-field (field)
(format t "~{~{~a~}~%~}" field))
(print-field (mk-tri 5))
;; *
;; **
;; ***
;; ****
;; *****
(defun invert-v (data)
(reverse data))
(print-field (invert-v (mk-tri 5)))
;; *****
;; ****
;; ***
;; **
;; *
(defun invert-h (data)
(mapcar #'reverse data))
(print-field (invert-h (mk-tri 5)))
;; *
;; **
;; ***
;; ****
;; *****
this would give you the whole new level of freedom, like you can imagine this little toolkit for patterns drawing:
(defun concat-v (d1 d2)
(append d1 d2))
(defun concat-h (d1 d2)
(mapcar #'append d1 d2))
(defun repeat-v (n data)
(reduce #'concat-v (loop repeat n collect data)))
(defun repeat-h (n data)
(reduce #'concat-h (loop repeat n collect data)))
(let* ((tri (mk-tri 5))
(tri2 (concat-v tri (invert-v tri)))
(rect (concat-h tri2 (invert-h tri2))))
(print-field (repeat-v 2 (repeat-h 3 rect))))
;; * ** ** *
;; ** **** **** **
;; *** ****** ****** ***
;; **** ******** ******** ****
;; ******************************
;; ******************************
;; **** ******** ******** ****
;; *** ****** ****** ***
;; ** **** **** **
;; * ** ** *
;; * ** ** *
;; ** **** **** **
;; *** ****** ****** ***
;; **** ******** ******** ****
;; ******************************
;; ******************************
;; **** ******** ******** ****
;; *** ****** ****** ***
;; ** **** **** **
;; * ** ** *
Upvotes: 1
Reputation: 139261
(defun triangle (k)
(cond ((or (not (integerp k))
(= k 0))
'("invalid number; please enter a positive or a negative integer"))
((< k -1)
(loop for x from k to -1 do
(loop for y from k to -1 do
(if (< y x)
(princ #\Space)
(princ '*)))
(terpri)))
((or (= k 1) (= k -1))
'*)
(t
(loop for x from 0 to k do
(loop for y from 0 to k do
(if (< x y)
(princ '*)))
(terpri))))
(values))
Example:
CL-USER 8 > (triangle 3)
***
**
*
CL-USER 9 >
Upvotes: 2