-
Notifications
You must be signed in to change notification settings - Fork 1
/
input-output.lisp
236 lines (206 loc) · 8.95 KB
/
input-output.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
;;; Chapter 9 - Input/Output
;;; Exercises.
;;; Ex 9.1
;;; Write a function to print the following saying on the display: "There are old pilots, and there are bold pilots, but there are no old bold pilots."
;;; The function should break up the quotation into several lines.
(defun print-test ()
(format t "There are old pilots,~&and there are bold pilots,~&but there are no old bold pilots.~& "))
;;; Ex 9.2
;;; Write a recursive function DRAW-LINE that draws a line of a specified length by doing (FORMAT T "*") the correct number of times.
;;; (DRAW-LINE 10) should produce **********
(defun draw-line (n)
(labels ((dl-helper (x result)
(cond ((>= x n) (mapcar #'(lambda (x) (format t x)) result))
(t (dl-helper (+ x 1) (cons "*" result))))))
(dl-helper 0 nil)))
(defun draw-line (n)
(cond ((zerop n) (format t "~%"))
(t (format t "*")
(draw-line (- n 1)))))
;;; Ex 9.3
;;; Write a recursive function DRAW-BOX that calls DRAW-LINE repeatedly to draw a box of specified dimensions.
;;; (DRAW-BOX 10 4) should produce:
**********
**********
**********
**********
(defun draw-box (x y)
(cond ((zerop y) (format t "~%"))
(t (draw-line x)
(format t "~%")
(draw-box x (- y 1)))))
;;; Ex 9.4
;;; Write a recursive function NINETY-NINE-BOTTLES that sings the well-known song "Ninety-nine Bottles of Beer on the Wall." The first verse of this song is:
;;; 99 bottles of beer on the wall,
;;; 99 bottles of beer!
;;; Take one down,
;;; Pass it around,
;;; 98 bottles of beer on the wall.
;;; NINETY-NINE-BOTTLES should take a number N as input and start counting from N down to zero. (This is so you can run it on three bottles instead of all ninety nine.)
;;; Your function should also leave a blank line between each verse, and say something appropriate when it runs out of beer.
(defun ninety-nine-bottles (n)
(cond ((zerop n) (format t "~%~S bottles of beer on the wall." n))
(t (format t "~&~S bottles of beer on the wall," n)
(format t "~&~S bottles of beer!" n)
(format t "~&Take one down,")
(format t "~&Pass it around,")
(ninety-nine-bottles (- n 1)))))
;;; Ex 9.5
;;; Part of any tic-tac-toe playing program is a function to display the board. Write a function PRINT-BOARD that takes a list of nine element as input. Each element will be an X, an O, or NIL. PRINT-BOARD should display the corresponding board.
;;; (PRINT-BOARD '(X O O NIL X NIL O NIL X)) should print:
X | O | O
-----------
| X |
-----------
O | | X
(defun repl (a b c)
(cond ((eq a b) c)
(t a)))
(defun print-board (l)
(cond ((null l) (format t "~%"))
(t (format t "~& ~A | ~A | ~A"
(repl (first l) nil " ")
(repl (second l) nil " ")
(repl (third l) nil " "))
(if (cdddr l)
(format t "~&-----------"))
(print-board (cdddr l)))))
(defun print-board (b)
(let ((b2 (sublis '((x . "X")
(o . "O")
(nil . " "))
b)))
(format t "~&")
(print-line b2)
(format t "-----------~%")
(print-line (nthcdr 3 b2))
(format t "-----------~%")
(print-line (nthcdr 6 b2))))
(defun print-line (line)
(format t " ~A | ~A | ~A~%"
(first line)
(second line)
(third line)))
;;; Ex 9.6
;;; Write a function to compute an hourly worker's gross pay given an hourly wage in dollars and the number of hours he or she worked.
;;; Your function should prompt for each input it needs by printing a message in English. It should display its answers in English as well.
(defun gross-pay ()
(format t "~&Please enter your hourly wage: ")
(let ((h (read)))
(format t "~&Please enter the working hours: ")
(let ((w (read)))
(format t "~&The gross pay is ~S €." (* h w)))))
;;; Ex 9.7
;;; The COOKIE-MONSTER function keeps reading data from the terminal until it reads the symbol COOKIE.
;;; Write COOKIE-MONSTER. Here is a sample interaction:
> (cookie-monster)
Give me cookie!!!
Cookie? rock
No want ROCK...
Give me cookie!!!
Cookie? cookie
Thank you!...Munch munch munch...BURP
NIL
(defun cookie-monster ()
(format t "~&Give me cookie!!!")
(format t "~&Cookie? ")
(let ((cookie (read)))
(cond ((string-equal cookie "cookie")
(format t "~&Thank you!...Munch munch munch...BURP"))
(t (format t "~&No want ~A..." cookie)
(cookie-monster)))))
;;; Ex 9.10
;;; As you write each of the following functions, test it by calling it from top level with appropriate inputs before proceeding on to the next function.
;;; a.
;;; Write a recursive function SPACE-OVER that takes a number N as input and moves the cursor to the right by printing N spaces, one at a time.
;;; SPACE should print "Error!" if N is negative.
;;; Test it by using the function TEST. Try (TEST 5) and (TEST -5).
(defun test (n)
(format t "~%>>>")
(space-over n)
(format t "<<<"))
(defun space-over (n)
(cond ((zerop n) nil)
((< n 0) (format t "Error!"))
(t (format t " ")
(space-over (- n 1)))))
;;; b.
;;; Write a function PLOT-ONE-POINT that takes two inputs PLOTTING-STRING and Y-VAL, prints PLOTTING-STRING (without the quotes) in column Y-VAL, and then moves to a new line.
;;; The leftmost column is numbered zero.
(defun plot-one-point ()
(format t "~&Enter plotting string: ")
(let ((plotting-string (read)))
(format t "~&Enter y-val: ")
(let ((y-val (read)))
(space-over y-val)
(format t "~A" plotting-string))))
(defun plot-one-point (plotting-string y-val)
(space-over y-val)
(format t "~A~%" plotting-string))
;;; c.
;;; Write a function PLOT-POINTS that takes a string and a list of y values as input and plot them. (PLOT-POINTS "<>" '(4 6 8 10 8 6 4)) should print
<>
<>
<>
<>
<>
<>
<>
(defun plot-points (str l)
(mapcar #'(lambda (x) (plot-one-point str x)) l))
;;; d.
;;; Write a function GENERATE that takes two numbers M and N as input and returns a list of the integers from M to N.
;;; (GENERATE -3 3) should return (-3 -2 -1 0 1 2 3).
(defun generate (m n)
(generate-helper m n nil))
(defun generate-helper (m n result)
(cond ((> m n) result)
(t (generate-helper (+ m 1) n (append result (list m))))))
;;; e.
;;; Write the MAKE-GRAPH function. MAKE-GRAPH should prompt for the values of FUNC, StART, END, and PLOTTING-STRING, and then graph the function.
;;; Note: You can pass FUNC as an input to MAPCAR to generate the list of y values for the function.
(defun make-graph ()
(format t "~&Function to graph? ")
(let ((func (read)))
(format t "~&Starting x value? ")
(let ((start (read)))
(format t "~&Ending x value? ")
(let ((end (read)))
(format t "~&Plotting string? ")
(let ((plotting-string (read)))
(plot-points plotting-string
(mapcar #'(lambda (x) (funcall func x)) (generate start end))))))))
;;; f.
;;; Define the SQUARE function and graph it over the range -7 to 7.
(defun square (x)
(* x x))
;;; Ex 9.11
;;; Write a function DOT-PRIN1 that takes a list as input and prints it in dot notation. DOT-PRIN1 will print parentheses by (FORMAT T "(") and (FORMAT T ")"), and dots by (FORMAT T " . "), and will call itself recursively to print lists within lists.
;;; DOT-PRIN1 should return NIL as its result.
;;; Try (DOT-PRIN1 '(A (B) C)) and see if your output matches the result in the table above.
;;; Then try (DOT-PRIN1 '((((A))))).
(defun dot-prin1 (l)
(cond ((atom l) (format t "~S" l))
(t (format t "(")
(dot-prin1 (car l))
(format t " . ")
(dot-prin1 (cdr l))
(format t ")"))))
;;; Ex 9.12
;;; Write HYBRID-PRIN1. Here is how the function should decide whether to print a dot or not. If the cdr part of the cons cell is a list, HYBRID-PRIN1 continues to print in list notation.
;;; If the cdr part is NIL, HYBRID-PRIN1 should print a right parenthesis.
;;; If the cdr part is something else, such as a symbol, HYBRID-PRIN1 should print a dot, the symbol, and a right parenthesis.
;;; It will be useful to define a subfunction to print cdrs of lists, as these always begin with a space, whereas the cars always begin with a left parenthesis.
(defun hybrid-prin1 (l)
(cond ((atom l) (format t "~S" l))
(t (hp-car (car l))
(hp-cdr (cdr l)))))
(defun hp-car (l)
(format t "(")
(hybrid-prin1 l))
(defun hp-cdr (l)
(cond ((null l) (format t ")"))
((atom l) (format t " . ~S)" l))
(t (format t " ")
(hybrid-prin1 (car l))
(hp-cdr (cdr l)))))