Question 1: Show that (F O(R-60 F) F) is a string in the language defined by our BNF grammar. To do this, you should start with CommandSequence, and show a sequence of replacements that follow the grammar rules that produce the target string. You can use the rule numbers above to identify the rules.
By rule 1, rewrite CommandSequence ::= ( CommandList ).
By rule 2, replace the CommandList in ( CommandList ) with Command CommandList to get (Command CommandList ).
For the rest of the steps, we will show the rewriting by identifying the rule we use, and underlining the part of the expression that changes.
Rule 4: (Command CommandList) ==> (F CommandList)
------- -
Rule 2: (F CommandList) ==> (F Command CommandList)
-----------
Rule 6: (F Command CommandList ==> (F OCommandSequence CommandList)
------- ----------------
Rule 1: (F OCommandSequence CommandList) ==> (F O(CommandList) CommandList)
--------------- -------------
Rule 2: (F O(CommandList) CommandList)
-----------
==> (F O(Command CommandList) CommandList)
-------------------
Rule 5: (F O(Command CommandList) CommandList)
-------
==> (F O(RAngle CommandList) CommandList)
------
Rule 7: (F O(RAngle CommandList) CommandList)
-----
==> (F O(R-60 CommandList) CommandList)
---
Rule 2: (F O(R-60 CommandList) CommandList)
-----------
==> (F O(R-60 Command CommandList) CommandList)
-------------------
Rule 4: (F O(R-60 Command CommandList) CommandList)
-------
==> (F O(R-60 F CommandList) CommandList)
-
Rule 3: (F O(R-60 F CommandList) CommandList)
-----------
==> (F O(R-60 F) CommandList)
Rule 2: (F O(R-60 F) CommandList)
-----------
==> (F O(R-60 F) Command CommandList)
-------------------
Rule 4: (F O(R-60 F) Command CommandList)
-------
==> (F O(R-60 F) F CommandList)
_
Rule 3: (F O(R-60 F) F CommandList) ==> (F O(R-60 F) F)
-----------
Since we were able to produce (F O(R-60 F) F) from
CommandSequence by following the replacement rules, we have
shown that (F O(R-60 F) F) is a string in the language.
(define (is-forward? lcommand)
(eq? (car lcommand) 'f))
(define (is-rotate? lcommand)
(eq? (car lcommand) 'r))
(define (is-offshoot? lcommand)
(eq? (car lcommand) 'o))
(define (get-angle lcommand)
(if (is-rotate? lcommand)
(cdr lcommand)
(error "Bad attempt to get angle")))
(define (get-offshoot-commands lcommand)
(if (is-offshoot? lcommand)
(cdr lcommand)
(error "Bad attempt to get offshoot commands")))
(if predicate consequent alternate)into an equivalent cond expression:
(cond (predicate consequent)
(else alternate))
Using if expressions we can transform the begin expression (begin Expr1 Expr2) into:
(if (or Expr1 #t)
Expr2
#f) ;; anything for alternate, since predicate is always true
Using application expressions:
((lambda (ignore) Expr2) Expr1)Note that the order is reversed here, since the operaned subexpression will be evaluated before the body expression.
(define (rewrite-lcommands lcommands replacement)
(flatten-commands
(map
(lambda (command)
(if (is-forward? command)
replacement ; forwards are replaced with replacement
(if (is-offshoot? command)
(make-offshoot-command
(rewrite-lcommands
(get-offshoot-commands command)
replacement))
(if (is-rotate? command)
command ; rotates are unchanged
(error "Bad command: " command)))))
lcommands)))
(define vertical-mid-line (lambda (t) (make-point 0.5 t))) (define (make-vertical-line x) (lambda (t) (make-point x t)))
(define (draw-half-line) (draw-curve-points (translate (shrink horiz-line 0.5) 0.5 0.5) 1000))
(connect-rigidly c1 (connect-rigidly c2 (connect-rigidly curve3 (... cn))))
(define (num-points p n) (if (= n 0) p (num-points (/ p 2) (- n 1))))
(define (convert-lcommands-to-curvelist lcommands)
(cond ((null? lcommands)
(list (lambda (t)
(make-colored-point 0.0 0.0
(make-color 0 255 0)))))
((is-forward? (car lcommands))
(cons-to-curvelist
(make-vertical-line (get-distance (car lcommands)))
(convert-lcommands-to-curvelist (cdr lcommands))))
((is-rotate? (car lcommands))
;;; Rotate every curve in the rest
(let
;; L-system turns are clockwise, so use - angle
((rotate-angle (- (get-angle (car lcommands)))))
(map
(lambda (curve)
(rotate-around-origin curve (get-angle (car lcommands))))
(convert-lcommands-to-curvelist (cdr lcommands)))))
((is-offshoot? (car lcommands))
(append
(convert-lcommands-to-curvelist
(get-offshoot-commands (car lcommands)))
(convert-lcommands-to-curvelist
(cdr lcommands)))
)
(#t (error "Bad lcommand!"))))
(define (make-lsystem-fractal replace-commands start level)
((n-times
(lambda (previous-commands)
(rewrite-lcommands previous-commands replace-commands))
level)
start))
Another possibility without using n-times:
(define (make-lsystem-fractal replace-commands start level)
(if (= level 0)
start
(make-lsystem-fractal replace-commands
(rewrite-lcommands start replace-commands)
(- level 1))))
Visit the Fractal Gallery at http://www.cs.virginia.edu/cs150/gallery/.