;;; Scheme Recursive Art Contest Entry ;;; ;;; Please do not include your name or personal info in this file. ;;; ;;; Title: Penrose Stars ;;; ;;; Description: ;;; If you invert this ;;; picture, you get a christmas- ;;; themed wrapping paper. ; NOTES: ; 1. https://en.wikipedia.org/wiki/Penrose_tiling ; 2. It's slow. Really slow. Go to line 130 and change the 7 to something ; <= 4 if you want to test this yourself. ; 3. I had to cut down the number of tokens, so things aren't as straightforward ; as they're supposed to be, and a few things that I'd rather not hardcode ; are hardcoded (such as colors). ; 4. By changing the subdivide algorithm, specifically lines 100 through 108, ; you will end up with a different penrose tilings. Somewhere online there ; should be algorithms if you need to find them. ; 5. If you change this file the line numbers will also change. ; TODOs: ; X. Reduce tokens to < 256 (done... for now) ; 2. Reduce (if possible) storage to linear space, if possible ; the only way this is possible is lazy evaluation of functions ; in particular, subdivide_triangles needs to be lazily evaluated. ; (right now the program can get unresponsive if subdivide_level > 6) (define (draw) ; a triangle is a list (a b c color), where a -> b -> c is its border ; and c is its fill color; a, b, c are coordinates: (x y) (define (a triangle) (car triangle)) (define (b triangle) (cadr triangle)) (define (c triangle) (cadr (cdr triangle))) (define (col triangle) (cadr (cdr (cdr triangle)))) ; unpacks a coordinate (x y) and sets turtle position (define (setcoordinates c) (setposition (car c) (cadr c))) ; draws a triangle; fill first, border second (define (draw_triangle triangle) (penup) (setcoordinates (a triangle)) (begin_fill) (setcoordinates (b triangle)) (setcoordinates (c triangle)) (setcoordinates (a triangle)) (color (col triangle)) (end_fill) ; for borders. uncomment if you want borders (+10 tokens) ;(color "#01bcb3") ;(pendown) ;(setcoordinates (b triangle)) ;(setcoordinates (c triangle)) ;(penup) ) ; draws a list of triangles; tail recursive (define (draw_triangles triangles) (if (pair? triangles) ((draw_triangle (car triangles)) (draw_triangles (cdr triangles))))) ; cadr (define (cadr li) (car (cdr li))) ; generates a "wheel": 10 triangles of the same color connected together ; like a pizza; this wheel is subdivided to create a penrose visual (define (generate_wheel scale rem last) (if (< rem 0) nil (let ((key (* rem 0.628318530717958647692528676655900576839433879875021164194))) ; that thing is pi/5, by the way; this is the only time we need to use pi (let ((current (list (* scale (sin key)) (* scale (cos key))))) (cons (if (even? rem) (list current '(0 0) last "#21ddd4") (list last '(0 0) current "#21ddd4")) (generate_wheel scale (- rem 1) current)))))) ; finds the golden ratio split (0.618/0.382 split) given two points (define (golden_ratio_split beginning end) (let ((phi 1.618033988749894848204586834365638117720309179805762862135)) (list (+ (car beginning) (/ (- (car end) (car beginning)) phi)) (+ (cadr beginning) (/ (- (cadr end) (cadr beginning)) phi))))) ; subdivides a triangle into a list of 2 or 3 new triangles (define (subdivide triangle) (let ((a (a triangle)) (b (b triangle)) (c (c triangle))) (let ((p (golden_ratio_split b c)) (q (golden_ratio_split c b)) (r (golden_ratio_split c a))) (if (equal? (col triangle) "#21ddd4") (list (list c a p "#21ddd4") (list b p a "#44fcf3")) (list (list b r a "#44fcf3") (list c q r "#44fcf3") (list b r q "#21ddd4")))))) ; subdivides a list of triangles; tail recursive (define (subdivide_triangles triangles result) (if (null? triangles) result (subdivide_triangles (cdr triangles) (append result (subdivide (car triangles)))))) ; subdivides a wheel many times to obtain a penrose visual; you must pass the ; result of generate_wheel as init; note that different visuals will be ; generated depending on whether level is even or odd (define (subdivide_level level init) (if (= level 0) init (subdivide_level (- level 1) (subdivide_triangles init '())))) ; a scale that will be used as radius of the penrose visual. (define effective_size (* 0.735294 (screen_width))) ; we finally start drawing (speed 0) (draw_triangles (subdivide_level 7 (generate_wheel effective_size 9 (list 0 effective_size)))) (hideturtle)) ; Please leave this last line alone. You may add additional procedures above ; this line. (draw)