72 |
irasnyd |
1 |
;Written By: Ira Snyder (parts from Dr. Soroka)
|
|
|
2 |
;Due Date: 02-28-2005
|
|
|
3 |
;Homework #: HW11
|
|
|
4 |
|
71 |
irasnyd |
5 |
; POLY.LSP
|
|
|
6 |
;
|
|
|
7 |
; add code for (* i2 i3) &c
|
|
|
8 |
;
|
|
|
9 |
; on T 050118 at 1730
|
|
|
10 |
; It reads & prints polynomials.
|
|
|
11 |
;
|
|
|
12 |
; on T 050118 at 0830
|
|
|
13 |
; All new.
|
|
|
14 |
; Brought over the ARITH code & began altering it to handle polynomials.
|
|
|
15 |
;
|
|
|
16 |
|
72 |
irasnyd |
17 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
18 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ASSUMPTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
19 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
20 |
;;; ;;;
|
|
|
21 |
;;; Since it was not specified, I decided to make POLY- work in same way ;;;
|
|
|
22 |
;;; as the lisp function -. (POLY- P1 P2) would be written in infix as ;;;
|
|
|
23 |
;;; P1 - P2. ;;;
|
|
|
24 |
;;; ;;;
|
|
|
25 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
71 |
irasnyd |
26 |
|
|
|
27 |
;
|
|
|
28 |
; Loop -- read:
|
|
|
29 |
; a polynomial
|
|
|
30 |
; or a reference
|
|
|
31 |
; or an expression involving references.
|
|
|
32 |
;
|
|
|
33 |
(defun POLY nil
|
|
|
34 |
(setf $HISTORY nil)
|
|
|
35 |
(let ((I 0)
|
|
|
36 |
(POLY))
|
|
|
37 |
(loop
|
|
|
38 |
(format t "~%(i~s) " I)
|
|
|
39 |
(setf INPUT (read))
|
|
|
40 |
(cond
|
|
|
41 |
((member INPUT '(exit halt quit stop)) (return nil))
|
|
|
42 |
((eq INPUT 'history) (SHOW-HISTORY))
|
|
|
43 |
((and (REFERENCEP INPUT) (not (VALID-REFERENCE-P INPUT)))
|
|
|
44 |
(format t "Reference out of range: ~s" INPUT)
|
|
|
45 |
)
|
|
|
46 |
((REFERENCEP INPUT) ; this reference is valid
|
|
|
47 |
(let ((OUTPUT (GET-REFERENCE INPUT)))
|
|
|
48 |
(format t "(o~s) " I)
|
|
|
49 |
(format t "~s~%" OUTPUT)
|
|
|
50 |
(setf $HISTORY (append $HISTORY (list OUTPUT)))
|
|
|
51 |
(setf I (1+ I))
|
|
|
52 |
)
|
|
|
53 |
)
|
|
|
54 |
((atom INPUT) (format t "Illegal expression: ~s" INPUT))
|
|
|
55 |
((VALID-OP-REF-REF INPUT)
|
|
|
56 |
(let ((OUTPUT (EXECUTE-EXPRESSION INPUT)))
|
|
|
57 |
(format t "(o~s)~%" I)
|
|
|
58 |
(WRITE-POLY OUTPUT)
|
|
|
59 |
(setf $HISTORY (append $HISTORY (list OUTPUT)))
|
|
|
60 |
(setf I (1+ I))
|
|
|
61 |
) ;end let
|
|
|
62 |
)
|
|
|
63 |
((not (VALID-IN-EXP INPUT)))
|
|
|
64 |
(t (let ((INTERMS (IE2INTERMS INPUT)))
|
|
|
65 |
(setf POLY (mapcar #'(lambda (INTERM) (VALID-INTERM nil INTERM))
|
|
|
66 |
INTERMS))
|
|
|
67 |
)
|
|
|
68 |
(format t "(o~s)~%" I)
|
|
|
69 |
(WRITE-POLY POLY)
|
|
|
70 |
(setf $HISTORY (append $HISTORY (list POLY)))
|
|
|
71 |
(setf I (1+ I))
|
|
|
72 |
)
|
|
|
73 |
) ;end cond
|
|
|
74 |
) ;end loop
|
|
|
75 |
) ;end let
|
|
|
76 |
) ;end defun
|
|
|
77 |
|
|
|
78 |
; VALID-OP-REF-REF recognizes forms like (* i2 i3)
|
|
|
79 |
; where the references are valid.
|
|
|
80 |
; Appropriate error messages are printed if needed.
|
|
|
81 |
(defun VALID-OP-REF-REF (EXP)
|
|
|
82 |
(cond
|
|
|
83 |
((not (= 3 (length EXP))) nil)
|
|
|
84 |
((not (member (car EXP) '(+ - *))) nil)
|
|
|
85 |
((not (VALID-REFERENCE-P (cadr EXP)))
|
|
|
86 |
(format t "Reference out of range: ~s" (cadr EXP))
|
|
|
87 |
nil)
|
|
|
88 |
((not (VALID-REFERENCE-P (caddr EXP)))
|
|
|
89 |
(format t "Reference out of range: ~s" (caddr EXP))
|
|
|
90 |
nil)
|
|
|
91 |
(t t)
|
|
|
92 |
)
|
|
|
93 |
)
|
|
|
94 |
|
|
|
95 |
;
|
|
|
96 |
; (VALID-REFERENCE-P S) returns T iff S is of the form i8 or o8 and the number
|
|
|
97 |
; specifies a valid $HISTORY entry.
|
|
|
98 |
;
|
|
|
99 |
(defun VALID-REFERENCE-P (S)
|
|
|
100 |
(and (REFERENCEP S)
|
|
|
101 |
(let ((N (parse-integer (subseq (symbol-name S) 1))))
|
|
|
102 |
(and (>= N 0) (< N (length $HISTORY)))
|
|
|
103 |
)
|
|
|
104 |
)
|
|
|
105 |
)
|
|
|
106 |
|
|
|
107 |
;
|
|
|
108 |
; (REFERENCEP S) returns T iff S is of the form i5 or o16 etc.
|
|
|
109 |
;
|
|
|
110 |
(defun REFERENCEP (S)
|
|
|
111 |
(and (symbolp S)
|
|
|
112 |
(or (char= #\I (char (symbol-name S) 0))
|
|
|
113 |
(char= #\O (char (symbol-name S) 0)))
|
|
|
114 |
(> (length (symbol-name S)) 1)
|
|
|
115 |
(DIGIT-STRING-P (subseq (symbol-name S) 1))
|
|
|
116 |
)
|
|
|
117 |
)
|
|
|
118 |
|
|
|
119 |
;
|
|
|
120 |
; (VALID-IN-EXP EXP)
|
|
|
121 |
;
|
|
|
122 |
; A valid IN-EXP is an append of valid INTERMs.
|
|
|
123 |
; E.g. (+ 3 - x ^ 2) is an append of (+ 3) and (- x ^ 2).
|
|
|
124 |
;
|
|
|
125 |
(defun VALID-IN-EXP (EXP)
|
|
|
126 |
(cond
|
|
|
127 |
((atom EXP) (format t "Sorry, but ~s is not legal here.~%" EXP)
|
|
|
128 |
nil)
|
|
|
129 |
(t (let ((INTERMS (IE2INTERMS EXP)))
|
|
|
130 |
(every #'(lambda (INTERM) (VALID-INTERM t INTERM))
|
|
|
131 |
INTERMS)
|
|
|
132 |
))
|
|
|
133 |
)
|
|
|
134 |
)
|
|
|
135 |
|
|
|
136 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
137 |
;;; SEE BELOW FOR IMPLEMENTATION OF WRITE-POLY ;;;
|
|
|
138 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
139 |
|
|
|
140 |
;
|
|
|
141 |
; (IE2INTERMS EXP) returns a list of the INTERMS in EXP.
|
|
|
142 |
; For example, (3 - x ^ 2 + 7 x) --> ((3) (- x ^ 2) (+ 7 x)).
|
|
|
143 |
; Note: Some may not be legal!
|
|
|
144 |
;
|
|
|
145 |
(defun IE2INTERMS (EXP)
|
|
|
146 |
(let ((RESULT nil)
|
|
|
147 |
(REST EXP))
|
|
|
148 |
(loop
|
|
|
149 |
(if (null REST) (return (reverse RESULT)))
|
|
|
150 |
(setf RESULT (cons (TAKE-INTERM REST) RESULT))
|
|
|
151 |
(setf REST (DROP-INTERM REST))
|
|
|
152 |
) ;end-loop
|
|
|
153 |
) ;end-let
|
|
|
154 |
)
|
|
|
155 |
|
|
|
156 |
;
|
|
|
157 |
; (TAKE-INTERM IN-EXP) returns the first INTERM of IN-EXP
|
|
|
158 |
;
|
|
|
159 |
(defun TAKE-INTERM (EXP)
|
|
|
160 |
(let ((INTERM (list (car EXP)))
|
|
|
161 |
(REST (cdr EXP)))
|
|
|
162 |
(loop
|
|
|
163 |
(if (null REST) (return (reverse INTERM)))
|
|
|
164 |
(if (member (car REST) '(+ -)) (return (reverse INTERM)))
|
|
|
165 |
(setf INTERM (cons (car REST) INTERM))
|
|
|
166 |
(setf REST (cdr REST))
|
|
|
167 |
) ;end loop
|
|
|
168 |
) ;end let
|
|
|
169 |
)
|
|
|
170 |
|
|
|
171 |
;
|
|
|
172 |
; (DROP-INTERM IN-EXP) returns ALL BUT the first INTERM of IN-EXP
|
|
|
173 |
;
|
|
|
174 |
(defun DROP-INTERM (EXP)
|
|
|
175 |
(let ((INTERM (list (car EXP)))
|
|
|
176 |
(REST (cdr EXP)))
|
|
|
177 |
(loop
|
|
|
178 |
(if (null REST) (return REST))
|
|
|
179 |
(if (member (car REST) '(+ -)) (return REST))
|
|
|
180 |
(setf INTERM (cons (car REST) INTERM))
|
|
|
181 |
(setf REST (cdr REST))
|
|
|
182 |
) ;end loop
|
|
|
183 |
) ;end let
|
|
|
184 |
)
|
|
|
185 |
|
|
|
186 |
;
|
|
|
187 |
; (VALID-INTERM PFLAG EXP)
|
|
|
188 |
;
|
|
|
189 |
; Convert things like (- 2 x ^ 7) into (-2 7) if possible.
|
|
|
190 |
; If not possible, then return nil.
|
|
|
191 |
; If PFLAG is T, then error messages are printed.
|
|
|
192 |
;
|
|
|
193 |
(defun VALID-INTERM (PFLAG EXP) (VALID-INTERM0 PFLAG EXP EXP))
|
|
|
194 |
|
|
|
195 |
;
|
|
|
196 |
; Grab off the sign, if any.
|
|
|
197 |
;
|
|
|
198 |
(defun VALID-INTERM0 (PFLAG INTERM L)
|
|
|
199 |
(cond
|
|
|
200 |
((atom L) (format PFLAG "Invalid INTERM: ~s" INTERM)
|
|
|
201 |
nil)
|
|
|
202 |
((eq '- (car L)) (VALID-INTERM1 PFLAG INTERM -1 (cdr L)))
|
|
|
203 |
((eq '+ (car L)) (VALID-INTERM1 PFLAG INTERM 1 (cdr L)))
|
|
|
204 |
(t (VALID-INTERM1 PFLAG INTERM 1 L))
|
|
|
205 |
)
|
|
|
206 |
)
|
|
|
207 |
|
|
|
208 |
;
|
|
|
209 |
; Grab off the coefficient, if any.
|
|
|
210 |
;
|
|
|
211 |
(defun VALID-INTERM1 (PFLAG INTERM SIGN L)
|
|
|
212 |
(cond
|
|
|
213 |
((null L) (format PFLAG "Invalid INTERM: ~s" INTERM)
|
|
|
214 |
nil)
|
|
|
215 |
((eq 'x (car L)) (VALID-INTERM2 PFLAG INTERM SIGN 1 L))
|
|
|
216 |
((numberp (car L)) (VALID-INTERM2 PFLAG INTERM SIGN (car L) (cdr L)))
|
|
|
217 |
(t (format PFLAG "Invalid INTERM -- numeric coefficient expected: ")
|
|
|
218 |
(format PFLAG "~s" INTERM)
|
|
|
219 |
nil)
|
|
|
220 |
)
|
|
|
221 |
)
|
|
|
222 |
|
|
|
223 |
;
|
|
|
224 |
; Handle constant terms here.
|
|
|
225 |
;
|
|
|
226 |
(defun VALID-INTERM2 (PFLAG INTERM SIGN COEF L)
|
|
|
227 |
(cond
|
|
|
228 |
((null L) (list (* SIGN COEF) 0))
|
|
|
229 |
((eq 'x (car L)) (VALID-INTERM3 PFLAG INTERM SIGN COEF (cdr L)))
|
|
|
230 |
(t (format PFLAG "Invalid INTERM -- X was expected: ")
|
|
|
231 |
(format PFLAG "~s" INTERM)
|
|
|
232 |
nil)
|
|
|
233 |
)
|
|
|
234 |
)
|
|
|
235 |
|
|
|
236 |
;
|
|
|
237 |
; No exponent exits here:
|
|
|
238 |
;
|
|
|
239 |
(defun VALID-INTERM3 (PFLAG INTERM SIGN COEF L)
|
|
|
240 |
(cond
|
|
|
241 |
((null L) (list (* SIGN COEF) 1))
|
|
|
242 |
((eq '^ (car L)) (VALID-INTERM4 PFLAG INTERM SIGN COEF (cdr L)))
|
|
|
243 |
(t (format PFLAG "Invalid INTERM -- ^ was expected: ")
|
|
|
244 |
(format PFLAG "~s" INTERM))
|
|
|
245 |
)
|
|
|
246 |
)
|
|
|
247 |
|
|
|
248 |
;
|
|
|
249 |
; Grab the exponent.
|
|
|
250 |
;
|
|
|
251 |
(defun VALID-INTERM4 (PFLAG INTERM SIGN COEF L)
|
|
|
252 |
(cond
|
|
|
253 |
((null L) (format PFLAG "Invalid INTERM -- exponent missing: ")
|
|
|
254 |
(format PFLAG "~s" INTERM))
|
|
|
255 |
((cdr L) (format PFLAG "Invalid INTERM -- extra stuff at end: ")
|
|
|
256 |
(format PFLAG "~s" INTERM))
|
|
|
257 |
((not (numberp (car L)))
|
|
|
258 |
(format PFLAG "Invalid INTERM -- exponent must be numeric: ")
|
|
|
259 |
(format PFLAG "~s" INTERM))
|
|
|
260 |
(t (list (* SIGN COEF) (car L)))
|
|
|
261 |
)
|
|
|
262 |
)
|
|
|
263 |
|
|
|
264 |
;
|
|
|
265 |
; (EXECUTE-EXPRESSION EXP) processes things like (* I5 i6).
|
|
|
266 |
;
|
|
|
267 |
(defun EXECUTE-EXPRESSION (EXP)
|
|
|
268 |
(let ((OP (car EXP))
|
|
|
269 |
(ARG1 (GET-REFERENCE (cadr EXP)))
|
|
|
270 |
(ARG2 (GET-REFERENCE (caddr EXP))))
|
|
|
271 |
(cond
|
|
|
272 |
((eq OP '*) (POLY* ARG1 ARG2))
|
|
|
273 |
((eq OP '+) (POLY+ ARG1 ARG2))
|
|
|
274 |
((eq OP '-) (POLY- ARG1 ARG2))
|
|
|
275 |
(t (format t "EXECUTE-EXPRESSION: Illegal operator: ~s" OP))
|
|
|
276 |
) ;end-cond
|
|
|
277 |
) ;end-let
|
|
|
278 |
)
|
|
|
279 |
|
|
|
280 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
281 |
;;; The below 3 functions (POLY*, POLY+, and POLY-) were implemented ;;;
|
|
|
282 |
;;; on 02-20-2005 by Ira Snyder for HW11 ;;;
|
|
|
283 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
284 |
|
|
|
285 |
;;; This function takes two polynomials represented in PNF,
|
|
|
286 |
;;; and returns the result of multiplying them together.
|
|
|
287 |
;;; The two do loops take each sublist of P1 and P2, and call
|
|
|
288 |
;;; POLY*1 on the two lists.
|
|
|
289 |
(defun POLY* (P1 P2)
|
|
|
290 |
(do ((P1 P1 (cdr P1))
|
|
|
291 |
(RESULT nil))
|
|
|
292 |
((null P1) RESULT)
|
|
|
293 |
(do ((P2 P2 (cdr P2)))
|
|
|
294 |
((null P2) RESULT)
|
|
|
295 |
(setf RESULT (cons (POLY*1 (car P2) (car P1)) RESULT))
|
|
|
296 |
)
|
|
|
297 |
)
|
|
|
298 |
)
|
|
|
299 |
|
|
|
300 |
;;; This function takes two pairs of numbers, each representing
|
|
|
301 |
;;; a coefficient and power of a variable. It returns the multiplication
|
|
|
302 |
;;; of these two pairs, as a new pair.
|
|
|
303 |
(defun POLY*1 (PAIR1 PAIR2)
|
|
|
304 |
(list (* (car PAIR1) (car PAIR2)) (+ (cadr PAIR1) (cadr PAIR2)))
|
|
|
305 |
)
|
|
|
306 |
|
|
|
307 |
;;; This function takes two lists, each in PNF, and returns a new
|
|
|
308 |
;;; list which is the addition of P1 and P2.
|
|
|
309 |
(defun POLY+ (P1 P2)
|
|
|
310 |
(do ((P1 P1 (cdr P1))
|
|
|
311 |
(RESULT P2))
|
|
|
312 |
((null P1) RESULT)
|
|
|
313 |
(setf RESULT (INSERT (car P1) RESULT))
|
|
|
314 |
)
|
|
|
315 |
)
|
|
|
316 |
|
|
|
317 |
;;; This function takes two lists, each in PNF, and returns a new
|
|
|
318 |
;;; list which is the subtraction of P2 from P1.
|
|
|
319 |
(defun POLY- (P1 P2)
|
|
|
320 |
(do ((P2 P2 (cdr P2))
|
|
|
321 |
(RESULT P1))
|
|
|
322 |
((null P2) RESULT)
|
|
|
323 |
(setf RESULT (INSERT (list (* -1 (caar P2)) (cadar P2)) RESULT))
|
|
|
324 |
)
|
|
|
325 |
)
|
|
|
326 |
|
|
|
327 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
328 |
;;; End of things implemented by Ira Snyder for HW11 ;;;
|
|
|
329 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
330 |
|
|
|
331 |
;
|
|
|
332 |
; (GET-REFERENCE REF) looks up things like I8 in $HISTORY.
|
|
|
333 |
; Assume that REF is legal.
|
|
|
334 |
;
|
|
|
335 |
(defun GET-REFERENCE (REF)
|
|
|
336 |
(let ((N (parse-integer (subseq (symbol-name REF) 1))))
|
|
|
337 |
(nth N $HISTORY)
|
|
|
338 |
)
|
|
|
339 |
)
|
|
|
340 |
|
|
|
341 |
;
|
|
|
342 |
; (DIGIT-STRING-P string) returns T iff all chars in STRING are digits.
|
|
|
343 |
;
|
|
|
344 |
(defun DIGIT-STRING-P (STR)
|
|
|
345 |
(let ((I 0))
|
|
|
346 |
(loop
|
|
|
347 |
(if (>= I (length STR)) (return t))
|
|
|
348 |
(if (not (digit-char-p (char STR I))) (return nil))
|
|
|
349 |
(setf I (1+ I))
|
|
|
350 |
) ;end loop
|
|
|
351 |
) ;end let
|
|
|
352 |
)
|
|
|
353 |
|
|
|
354 |
(defun SHOW-HISTORY nil
|
|
|
355 |
(let ((I 0))
|
|
|
356 |
(mapc #'(lambda (ITEM) (format t ">(i~s) ~s~%" I ITEM)
|
|
|
357 |
(setf I (1+ I)))
|
|
|
358 |
$HISTORY)
|
|
|
359 |
)
|
|
|
360 |
)
|
|
|
361 |
|
|
|
362 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
363 |
;;; Below is code added by Ira Snyder on 02-20-2005 ;;;
|
|
|
364 |
;;; This code implements WRITE-POLY, PNF and all supporting ;;;
|
|
|
365 |
;;; functionsfrom HW08 ;;;
|
|
|
366 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
367 |
|
|
|
368 |
;;; Given a list in unsorted, unreduced Polynomial
|
|
|
369 |
;;; Normal Form, and returns a list in perfect PNF
|
|
|
370 |
(defun PNF (L)
|
|
|
371 |
(do ((L L (cdr L))
|
|
|
372 |
(RET nil))
|
|
|
373 |
((null L) RET)
|
|
|
374 |
(setf RET (INSERT (car L) RET))
|
|
|
375 |
(setf RET (DEL-ZERO-COEF RET))
|
|
|
376 |
)
|
|
|
377 |
)
|
|
|
378 |
|
|
|
379 |
;;; Given a pair of numbers (in a list) and a list of pairs
|
|
|
380 |
;;; this inserts the pair into the list in it's correct place
|
|
|
381 |
;;; including combining coefficients
|
|
|
382 |
(defun INSERT (PAIR LIST)
|
|
|
383 |
(let ((FPTR (caar LIST))) ;this is needed so we don't change
|
|
|
384 |
;the list outside this function
|
|
|
385 |
(cond
|
|
|
386 |
((null LIST) (cons PAIR LIST))
|
|
|
387 |
((> (cadr PAIR) (cadar LIST)) (cons PAIR LIST))
|
|
|
388 |
((= (cadr PAIR) (cadar LIST)) (progn
|
|
|
389 |
(setf FPTR (+ (car PAIR) FPTR))
|
|
|
390 |
(cons (list FPTR (cadar LIST))
|
|
|
391 |
(cdr LIST))))
|
|
|
392 |
(t (cons (car LIST) (INSERT PAIR (cdr LIST))))
|
|
|
393 |
)
|
|
|
394 |
)
|
|
|
395 |
)
|
|
|
396 |
|
|
|
397 |
;;; Deletes all of the pairs that have zero coefficients in
|
|
|
398 |
;;; a PNF list
|
|
|
399 |
(defun DEL-ZERO-COEF (L)
|
|
|
400 |
(cond
|
|
|
401 |
((null L) nil)
|
|
|
402 |
((= 0 (caar L)) (DEL-ZERO-COEF (cdr L)))
|
|
|
403 |
(t (cons (car L) (DEL-ZERO-COEF (cdr L))))
|
|
|
404 |
)
|
|
|
405 |
)
|
|
|
406 |
|
|
|
407 |
;;; This takes a non-negative integer, and returns a string
|
|
|
408 |
;;; containing the number of spaces specified by the integer
|
|
|
409 |
(defun SPACES (N)
|
|
|
410 |
(do ((N N (1- N))
|
|
|
411 |
(STR (format nil "")))
|
|
|
412 |
((zerop N) STR)
|
|
|
413 |
(setf STR (concatenate 'string STR " "))
|
|
|
414 |
)
|
|
|
415 |
)
|
|
|
416 |
|
|
|
417 |
;;; This checks if nil was passed. If it was, print a blank line, then
|
|
|
418 |
;;; a "0" line. Else pass the list off to the WRITE-POLY1 function.
|
|
|
419 |
(defun WRITE-POLY (L)
|
|
|
420 |
(cond
|
|
|
421 |
((null L) (format t "~%0~%"))
|
|
|
422 |
(t (WRITE-POLY1 L))
|
|
|
423 |
)
|
|
|
424 |
)
|
|
|
425 |
|
|
|
426 |
;;; Given a list in Polynomial Normal Form, this will print
|
|
|
427 |
;;; the human readable form of the list on two lines.
|
|
|
428 |
;;; Example:
|
|
|
429 |
;;; INPUT: ((1 1) (2 3) (-10 0) (3 2) (2 1))
|
|
|
430 |
;;; OUTPUT: 3 2
|
|
|
431 |
;;; OUTPUT: + 2 x + 3 x + 3 x - 10
|
|
|
432 |
(defun WRITE-POLY1 (L)
|
|
|
433 |
(do ((L (PNF L) (cdr L))
|
|
|
434 |
(EXP (format nil ""))
|
|
|
435 |
(COEF (format nil "")))
|
|
|
436 |
((null L) (format t "~A~%~A~%" EXP COEF))
|
|
|
437 |
(setf COEF (concatenate 'string COEF (WRITE-NUM (caar L) (cadar L))))
|
|
|
438 |
(MAKE-EQUAL EXP COEF)
|
|
|
439 |
(setf EXP (concatenate 'string EXP (WRITE-EXP (caar L) (cadar L))))
|
|
|
440 |
(MAKE-EQUAL EXP COEF)
|
|
|
441 |
)
|
|
|
442 |
)
|
|
|
443 |
|
|
|
444 |
;;; Given a coefficient and an exponent, output the correct expression
|
|
|
445 |
;;; to represent it.
|
|
|
446 |
;;; Examples:
|
|
|
447 |
;;; INPUT: 3 4
|
|
|
448 |
;;; OUTPUT: + 3 x
|
|
|
449 |
;;;
|
|
|
450 |
;;; INPUT: 3 0
|
|
|
451 |
;;; OUTPUT: + 3
|
|
|
452 |
;;;
|
|
|
453 |
;;; INPUT: -3 0
|
|
|
454 |
;;; OUTPUT: - 3
|
|
|
455 |
(defun WRITE-NUM (NUM EXP)
|
|
|
456 |
(cond
|
|
|
457 |
; don't output an x if we have a zero exponent
|
|
|
458 |
((zerop EXP) (if (plusp NUM) (format nil " + ~A" NUM)
|
|
|
459 |
(format nil " - ~A" (abs NUM))))
|
|
|
460 |
((plusp NUM) (format nil " + ~A x" NUM))
|
|
|
461 |
(t (format nil " - ~A x" (abs NUM)))
|
|
|
462 |
)
|
|
|
463 |
)
|
|
|
464 |
|
|
|
465 |
;;; Given a coefficient and an exponent, output the exponent.
|
|
|
466 |
;;; NOTE: I chose to have the syntax of WRITE-EXP match the syntax of WRITE-NUM
|
|
|
467 |
;;; even though I do not use the parameter NUM in the code. This was for
|
|
|
468 |
;;; uniformity reasons.
|
|
|
469 |
(defun WRITE-EXP (NUM EXP)
|
|
|
470 |
(cond
|
|
|
471 |
((zerop EXP) nil)
|
|
|
472 |
((= EXP 1) nil)
|
|
|
473 |
(t (format nil "~A" EXP))
|
|
|
474 |
)
|
|
|
475 |
)
|
|
|
476 |
|
|
|
477 |
;;; When called with two strings as arguments, this macro expands to
|
|
|
478 |
;;; make them the same length, regardless of which is longer.
|
|
|
479 |
(defmacro MAKE-EQUAL (S1 S2)
|
|
|
480 |
`(cond
|
|
|
481 |
((> (length ,S1) (length ,S2)) (let ((DIFF (- (length ,S1) (length ,S2))))
|
|
|
482 |
(setf ,S2 (concatenate 'string ,S2 (SPACES DIFF)))))
|
|
|
483 |
((< (length ,S1) (length ,S2)) (let ((DIFF (- (length ,S2) (length ,S1))))
|
|
|
484 |
(setf ,S1 (concatenate 'string ,S1 (SPACES DIFF)))))
|
|
|
485 |
(t nil)
|
|
|
486 |
)
|
|
|
487 |
)
|
|
|
488 |
|