1 ;; TWENTY CHALLENGES FOR GREAT JUSTICE
\r
2 ;; ===================================
\r
11 ;; Define a macro THUNK which will wrap the body of the macro inside a lambda. That
\r
19 ;; (lambda () <body>)
\r
25 ; First, tell me why this can't be a function.
\r
26 ; Then implement it as a macro. --> A procedure called
\r
27 ; SET-IF! such that (set-if! pred sym val) sets the value of SYM to VAL
\r
28 ; only if PRED is true. Otherwise, it does nothing.
\r
29 ; (or if you want, otherwise, it just gives back NIL)
\r
31 (define-syntax set-if!
\r
33 ((_ pred sym val) (if pred
\r
36 (macroexpand '(set-if! #f a 5))
\r
42 ; Quadrescence | qu1j0t3, EXERCISE: Write a version of LETREC which
\r
43 ; allows one to use DEFINE syntax.
\r
44 ; I think that syntax is more consistent with
\r
45 ; general scheme syntax anyway. It's a little baroque
\r
46 ; and definitely not "minimal" but neither is being able
\r
47 ; to do (define (f x) ...)
\r
48 ; when (define f (lambda (x) ...)) works fine
\r
50 ; (define (example x)
\r
52 ; ((define (is-even? x) (zero? (remainder x 2)))
\r
53 ; (define rofl "rolling on the floor laughing"))
\r
58 (define-syntax with-definitions
\r
59 (syntax-rules () ())
\r
61 (syntax->datum (syntax (foo bar baz)))
\r
66 ; Qworkescence | Similar in spirit to the counting change problem,
\r
67 ; write a function to compute the "partitions of an integer".
\r
68 ; A partition of N is some sum of smaller numbers that add to N.
\r
69 ; So the partitions of 4 are (4) (3 1) (2 2) (2 1 1) (1 1 1 1)
\r
74 ; Quadrescence | CHALLENGE: replicate SML's reference type in scheme
\r
75 ; | (define a (ref 9))
\r
79 ; | you can use "deref" instead of "val"
\r
84 ; Quadrescence | CHALLENGE: write bogosort
\r
89 ; Quadrescence | replicate the behavior of ye olde lisp's SETQ,
\r
90 ; which is like SET! but allows several pairs of idents and vals
\r
91 ; e.g., (setq x 1 y 2 z 3)
\r
92 ; x is set to 1, y to 2, z to 3
\r
97 ; @Quadrescence | CHALLENGE: Make a macro (define* (f args) body)
\r
98 ; which defines f to be memoized: when you call f with
\r
99 ; arguments x, it'll save the value of the result
\r
100 ; so next time around, it just looks up the result.
\r
101 ; Extra credit: Do it without polluting the namespace
\r
102 ; (except w/ the function name of course)
\r
107 ; In challenge #8, you wrote a memoizing
\r
108 ; DEFINE macro called DEFINE*. However,
\r
109 ; this can be awkward and even inefficient
\r
110 ; when we have a COND or CASE. Consider:
\r
113 ; (cond ((= n 0) 0)
\r
115 ; (else (+ (fib (- n 1))
\r
116 ; (fib (- n 2))))))
\r
118 ; Each time we compute a yet-uncomputed
\r
119 ; fibonacci, we have to check if it's 0
\r
120 ; first, then 1, then we can procede to
\r
123 ; In this challenge, we want to be allowed
\r
124 ; to define constant cases which add to
\r
125 ; the hash table immediately. Let's call
\r
126 ; this definition procedure DEF.
\r
133 ; (n) => (+ (fib (- n 1))
\r
136 ; This will create a function FIB which will
\r
137 ; have zero and one memoized, and allow for
\r
138 ; the general case. When we do call the general
\r
139 ; case for an unmemoized function, we no longer
\r
140 ; have to crawl the COND, because there is none.
\r
141 ; So we save comparisons each time it's called.
\r
143 ; For multi-argument functions, it would be illegal to have (4 b c) => ...
\r
145 ; you can safely assume the last case will be the variable case
\r
150 ; @Quadrescence | qu1j0t3: this one isn't tough, but it's an important
\r
151 ; demonstration. Write a macro "with-degrees"
\r
152 ; which causes all trig functions (sin cos tan) to use degrees
\r
153 ; and not radians. Therefore if there is a
\r
154 ; (sin x), it should be changed to (sin (* pi (/ 180) x)),
\r
155 ; where pi=3.14159265358979
\r
156 ; (with-degrees (+ (sin 30) (sin 90))) should give 1.5
\r
161 ; Quadrescence | as an exercise, you should implement a C-style FOR loop:
\r
162 ; (for ((<var> <init>) <condition> <post-loop-thing>) <body>)
\r
164 ; and <var>'s scope should be limited to FOR
\r
165 ; example: (for ((i 0)
\r
167 ; (set! i (+ 1 i)))
\r
170 ; which would print 0 thru 9
\r
171 ; UNLIKE C, i's scope is limited
\r
172 ; Quadrescence | Now extend FOR so you can do (for (<VAR> <LST>) ...)
\r
173 ; and it will iterate over the list
\r
174 ; (this is equivalent to CL's DOLIST macro)
\r
179 // Quadrescence | write a program which takes a sentence (you can assume no punctuation)
\r
180 // and mixes the middle letters of the words randomly, and writes it to stdout
\r
181 // based on that classic thing where you can read text even if the middle letters
\r
182 // are scrambled, but the first and last remain the same
\r
188 ; I think you should create the macro you suggested. In Common Lisp,
\r
189 ; this macro is DESTRUCTURING-BIND. One way it works is like this (schemified):
\r
190 ; (define *list* '(1 2 3))
\r
191 ; (destructuring-bind (a b c) *list*
\r
198 ; Qworkescence | But the last time I wrote an infix parser was for an
\r
199 ; arithmetic expression parser which recognizes
\r
200 ; associativity of operands and the natural solution is
\r
201 ; from our friend Dijkstra and his beautifully simple
\r
202 ; Shunting Yard algorithm
\r
203 ; Qworkescence | Exercise: Read about & implement shunting yard
\r
204 ; Qworkescence | (in Scheme)
\r
209 ; Qworkescence | qu1j0t3, easy exercise: write the following functions
\r
210 ; in Scheme equivalent to their Common Lisp counterparts:
\r
211 ; (CONSTANTLY x) which returns a function which takes
\r
212 ; any number of args but always returns x
\r
214 ; and (COMPLEMENT fn) which takes a boolean function fn
\r
215 ; and returns the logical inverse (NOT) of it
\r
217 ; Qworkescence | CHALLENGE: If COMPLEMENT is the analog of the boolean
\r
218 ; function NOT, then write two functions (CONJUNCTION f g)
\r
219 ; which returns a function which takes an argument
\r
220 ; and checks if both f and g are satisfied.
\r
222 ; And write (DISJUNCTION f g) which returns a function
\r
223 ; which takes an argument and checks if either f or g are
\r
226 ; (clearly CONJUNCTION is the analog of boolean AND,
\r
227 ; and DISJUNCTION is the analog of boolean OR)
\r
228 ; if you have CONJUNCTION, then you can do stuff like...
\r
229 ; (define (divisible-by n)
\r
230 ; (lambda (x) (zero? (remainder x n))))
\r
231 ; (filter (conjunction (disjunction (divisible-by 3)
\r
232 ; (divisible-by 5))
\r
233 ; (complement (divisible-by 15)))
\r
235 ; filter those elements divisible by 3 or 5 and not 15
\r
240 ; Quadrescence | write (transpose matrix) which transposes.
\r
241 ; Quadrescence | If you don't know what transposition is,
\r
242 ; every row becomes a column, vice versa
\r
247 ; qu1j0t3 | Quadrescence: (diagonal? might be a nice scheme challenge..
\r
248 ;Quadrescence | first make a function called "square-matrix?" to see
\r
249 ; if it's even a matrix
\r
250 ; then write diagonal? to determine if the matrix is a diagonal
\r
256 ;15:41:53 Quadrescence | FurnaceBoy: Oh, another "small" Scheme challenge:
\r
257 ; Given a list of functions L = (f1 f2 ... fn) and a value x, write a
\r
258 ; function (appList F x) := ((f1 x) (f2 x) ... (fn x)) ¦
\r
259 ; e.g., if L = (sin cos tan), then (appList L 3.14) gives
\r
260 ; (0.00159265291648683 -0.99999873172754 -0.00159265493640722)
\r
265 Furthermore, make (appList* L) return a function such that ((appList* L) x) is
\r
266 equivalent to appList in Challenge 18
\r
271 Write a macro LOCALS which acts sort of like LET, but allows uninitialized values
\r
272 (you may initialize them to #f). For example
\r
274 (locals (a b (c 1) d)
\r
285 Write define-curried which defines a curried function. That is,
\r
286 (define-curried-function (clog b x) (/ (log x) (log b))), which sets clog to
\r
294 Write (@ f x y z ...) which applies f to x, then the result to y, etc. For
\r
295 example, (@ clog 2 5) ==> ((clog 2) 5)
\r
300 The tangent of a number tan(x) is defined as sin(x)/cos(x). We can
\r
301 compute tangent by using the definition, or we can make use of the
\r
302 so called "addition formula". The addition formula for tangent is
\r
305 tan(a + b) = ----------------- .
\r
308 If we wish to compute tan(x), then we can compute tan(x/2 + x/2):
\r
310 x x tan(x/2) + tan(x/2) 2*tan(x/2)
\r
311 tan(- + -) = --------------------- = ---------------- .
\r
312 2 2 1 - tan(x/2)*tan(x/2) 1 - (tan(x/2))^2
\r
314 We also know something about tangent when the argument is small:
\r
316 tan(x) ~= x when x is very close to 0.
\r
318 The exercise has two parts:
\r
320 (1) Write a recursive function TANGENT using the methods above
\r
321 to compute the tangent of a number. It is not necessary to
\r
322 handle undefined cases (odd multiples of pi/2).
\r
324 (2) Write an iterative version TANGENT-ITER of (1) which avoids
\r
325 tree recursion (uses named-LET or tail-recursive procedures).
\r
328 TEST CASES: Your values need not match these precisely (due to
\r
329 floating point error and implementation specifics).
\r
333 > (tangent-iter 1.0)
\r
335 > (tangent-iter 2.0)
\r
336 -2.1850435345286616
\r
337 > (tangent-iter (/ 3.14159 4))
\r