Our goal is to create a new function
star
, so that star 12, blue
draws a blue twelvepointed star.
Introduction to Functions
Here is the most important concept in all of programming:
A function is a miniature program. In CoffeeScript,
a function is written with an arrow >
typed
as two symbols next to each other (the minus and
the greaterthan) like this:
(input) > something to do
Writing and Naming Functions
A function that advances the turtle by ten times a distance is
(x) > fd 10 * x
Name a function like any variable,
using =
.
scoot = (x) > fd 10 * x
After the definition, we can write
scoot 7
or scoot 5 + 2
.
In other words, scoot
can be used just
like predefined functions like fd
or rt
.
Making a star
Function
Functions can be long.
This code defines a star
function
using indented lines after the >
:
star = (n, k) > # define a function star with two inputs and code to follow: pen k # use the chosen color. for [1..n] # repeat the following n times: fd 100 # move forward. rt 2 * 360 / n # turn right using a magic star formula. speed 10 # draw fast! star 7, red # use our newlydefined function!
Exercises
star
function, and save it as "star1". Some tips:
>
.
star = ...
will
not run it yet.
To run it you must use it:
star 7, red
.
star
function with
different numbers, and note the outcomes below:
Test  Outcome  Test  Outcome 
star 5, red 
star 9, red 

star 6, red 
star 10, red 

star 7, red 
star 11, red 

star 8, red 
star 12, red 
Debugging the Algorithm
There is a problem with
star
whenever we ask for
an even number of points:
star = (n, k) > pen k for [1..n] fd 100 rt 2 * 360 / n speed 10 star 8, red
What causes the bug?
The problem is in the "magic" formula
2 * 360 / n
.
To understand, read on.
The Geometry of Stars
Drawing a star is similar to drawing
a regular polygon. After the turtle has
gone all the way around all n
corners, it will come back to where it
started, facing the same direction it started.
The difference between a star and a polygon is its winding number: In a polygon, all the turns total up to 360° because each of the n turns is (360/n)°. So the turtle winds once around the center: its "winding number" is 1. In a star, the turtle turns total to a larger multiple of 360, such as 2×360, which gives it a winding number of 2.
If we change the "magic formula" to
3 * 360 / n
, we will get
a star with winding number 3. That
experiment is shown below.
star = (n, k) > pen k for [1..n] fd 100 rt 3 * 360 / n speed 10 star 8, red
The problem is this: if the winding number evenly divides the number of corners, we retrace old corners exactly. For example, when using the winding number 2 with 8 points, 2 divides 8, and we retrace the same 4 corners twice. The winding number 3 works better.
An Algorithm With an Answer: Picking a Winding Number
How do we pick a winding number for
an n
pointed star? We can write
an algorithm for that!
n
points:
c
from 2 to n as follows:
c
not a divisor
of n:
c
is our answer.
Translated from words into CoffeeScript:
winding = (n) > # define a function named winding. for c in [2..n] # vary c from 2 to n, starting at 2. if (n % c) isnt 0 # if c is not a divisor of n then: return c # c is the answer. write winding 8 # run our function and write the answer.
Here are tools that we used to write this algorithm in CoffeeScript:
for c in [2..n] 
Control.
Here c is a
looping variable.
When for is used with a
looping variable, it repeats its block
of code once for each value of
in the range, or until a special
command like return
quits the loop.

if 
Control.
if condition
runs the indented code only when the condition is true.

% 
Arithmetic.
The "modulo" arithmetic operator, written
using the percent symbol
x % y , calculates the remainder
when x is divided by y .
For example,
15 % 5 15 % 4 is 3.

isnt 
Arithmetic.
x isnt y tests
if two values are unequal. For example,
(n % c) isnt 0 n is divided by c .

return 
Control. When inside a function,
return answer ends the
calculation.

Exercises
winding
function, and save it as
"winding". Remember:
while
will happen inside the loop.
return
the answer outside the loop, return
should
not be doublyindented. But since the
return
is part of the function,
it should be singlyindented.
winding
function with
different numbers, and note the outcomes below:
Test  Outcome  Test  Outcome 
winding 5 
winding 9 

winding 6 
winding 10 

winding 7 
winding 11 

winding 8 
winding 12 
Using one Function inside Another
After we define winding
, we can
use it anywhere, including inside the
star
function. Here is how:
winding = (n) > # define the function winding for c in [2..n] if (n % c) isnt 0 return c star = (n, k) > # define the function star pen k w = winding n # use winding to pick w for [1..n] fd 100 rt w * 360 / n # use w as the winding number star 12, purple # draw a star!
The Importance of Testing
It is important to test algorithms! If you
test this algorithm carefully, you will find that
it still does not work for some values
of n
. For example,
star 18, red
draws a shape
with only 9 stars.
It turns out that a better way to choose a winding number is to choose a number that has no common divisors with n (other than 1).
The following is Euclid's algorithm to calculate the greatest common divisor of two numbers:
gcd = (a, b) > while b isnt 0 # repeat the indented lines while b isn't zero: if a > b # if a is greater than b, then do this: a = a  b # replace a with the difference (a  b) else # otherwise (if a is not greter than b): b = b  a # replace b with the difference (b  a) return a # after the loop is done, the answer is a
If a
and b
have
no common divisors, then gcd(a, b)
is 1.
Exercises
winding
to use
gcd
instead of %
:
gcd
to your program before you use it.
c
that
satisfies the condition gcd(n, c) is 1
.
star 18, red
? ______
n
. Create a program "star4" that
produces pointy stars:
floor
rounds down, so floor(n/2)
is half of
n
, rounded down.
for [floor(n/2)..1]
.
n
does star
draw the leastpointy
shape? ______
speed Infinity
,
pen path
and fill gold
.