Plot a spiral
A Theodorus spiral with plot
instead of turtles
. The coding went quickly because it was easy to translate into Racket the math from Python code.
The turtles version (fn:2)took a long time because I had to learn the math(fn:3) on my own.
Python Code
The math part
def next_vertex(x, y):
h = (x**2 + y**2)**0.5
return (x - y/h, y + x/h)
; https://www.johndcook.com/blog/2019/08/04/spiral-of-theodorus/
Racket Code
#lang racket
(require plot)
(define (sqr n)
(* n n))
(define (next-vertex xy-vector)
(match-define (vector x y) xy-vector)
(define h (sqrt (+ (sqr x) (sqr y))))
(vector (- x (/ y h)) (+ y (/ x h))))
; plot lines for short-side and hypotenuse of triangle
(define (short-hypo-lines xy-vec)
(define new-xy
(next-vertex xy-vec))
(list (lines (list xy-vec new-xy))
(lines (list (vector 0 0) new-xy))))
;; Setting the N limit to 17 overlaps the first segment
(define N 16)
(define x-start 1)
(define y-start 0)
(define (spiral limit)
;; in place of `for` and `range` a recursive function with helper-auxiliary
(define (helper lim xy-vec lines)
(cond
((= 0 lim) lines)
(#t (helper (sub1 lim)
(next-vertex xy-vec)
(cons
(short-hypo-lines xy-vec)
lines)))))
;; starting plot at x-start, y-start
(helper limit (vector x-start y-start) '()))
; View in DrRacket or Emacs Geiser REPL
(parameterize
((plot-decorations? #f))
; in Python versionplt.axis('off')
(plot (list
; get started with first line from 0,0 to x-start, y-start
(lines (list (vector 0 0)(vector x-start y-start)))
;; plot the short-side and hypotenuse for the right triangles
;; that make form the spiral
(spiral N))))
; save plot to png file for on-line sharing
; ; from Python version plt.savefig("theodorus.png")
(define spiral-bmp-1
(parameterize
((plot-decorations? #f))
(plot-bitmap (list
;; plot first line from 0,0 to x-start,y-start
(lines (list (vector 0 0)(vector x-start y-start)))
;; plot the short-side and hypotenuse for the right triangles
;; that form the spiral
(spiral N)))))
(send spiral-bmp-1 save-file "spiral-1-vector.png" 'png)
Translating the math from Python gave me chance to use match-define
and to get a feel for using vectors directly with plot
. Earlier work with plot
had me map
ping vector
over lists. My first script used lists and list->vector
, then I saw that the code could be shortened by using vectors from the start ( next-vertex
) and adjusting all the code to work with vector
. I still have to think about why next-vertex
works.
Recursion in general and named let in particular provide a natural way to implement many algorithms, whether iterative, recursive, or partly iterative and partly recursive; the programmer is not burdened with two distinct mechanisms. — Kent Dybvig in The Scheme Programming Language Ch 3: Going Further
As an amateur programmer recursive functions with internal helpers seem to be the only structure (construct? pattern?) that I need. With recursive functions I am not “burdened with ... distinct mechanisms” and feel comfortable building the lists that are needed for various tasks. The recursive functions with helper
functions may be the equivalent the of the Basic English (C.K. Ogden's) sentences at the start of English Through Pictures (I.A. Richards's):
– I took the book off the table.
– I put the book on the table.
– I gave the book to her.
– I went to the table.
– I put the book in the box.
– I took the book from the box.
footnotes and links
- (fn:1) https://www.johndcook.com/blog/2019/08/04/spiral-of-theodorus/
- that matlibplot code above inspired the turtles code below:
- the Python code above inspired my Racket code below:
- (fn:2) https://write.as/bs2lr/turtles-do-a-spiral
- the turtle code above needed the math knowledge below:
- (fn:2) https://write.as/bs2lr/turtles-do-a-spiral
(define N 26)
(define x-start 3)
(define y-start 0)
#Plot #TheodorusSpiral #Python #IaRichards #IaR #CKOgden #OgdensBasicEnglish