In the previous section, we didn't give the specifics of exactly how we generated the Koch curve of level 5 which we showed. The general procedure was pointed out (``Begin with F. Replace each F with FLFRRFLF. Repeat 5 times.''), but if you actually tried to do it yourself, you might have found it a bit tricky. Since the turtle command for the curve has 2388 letters, certainly it isn't something you would expect someone to type in directly.
Instead, a small maple procedure was written to generate it. Before giving the details, let's analyze the process a bit. We shall rely heavily on the self-similar nature of the Koch curve .
Notice that the curve is made up of four small copies of itself, arranged as
The second definition is much simpler to implement in a programming language which allows recursive functions, such as maple.5.5To see this, let's implement the factorial function in both ways:
>
fact1 := proc(n::posint)
local i,ans;
ans := 1;
for i from 1 to n do
ans := ans*i;
od;
ans;
end:
>
fact2 := proc(n::posint)
if (n=1) then
1;
else
n*fact2(n-1);
fi;
end:
Notice how much shorter and clearer the second version is.5.6 However, there is a price to pay: a recursively defined function has a bit more overhead than a non-recursive one. However, the savings in simplicity often overwhelms the minor loss in speed.5.7
To test your understanding, you might try to write a procedure to generate the Fibonacci numbers, which are defined by
With the idea of recursion in our bag of tools, we can now easily write our procedure to generate the Koch curve, using the observation we made in §3, namely that
>
Koch:= proc (n::nonnegint)
if (n=0) then
`F`;
else
cat( Koch(n-1), `L`, Koch(n-1), `RR`, Koch(n-1), `L`, Koch(n-1));
fi;
end:
> Koch(2);
If you think about it for a second, you might notice that what we have just
done is to write a little program (Koch
) whose output is a program in
another language (the string of turtle commands which describe
Kn). While this may seem odd at first, doing this sort of thing is
not at all uncommon.
Often, one sees the curve as one side of a closed plane figure, the Koch Snowflake (sometimes also called the ``Koch Island''). This is an infinite length ``curve'' which bounds a finite area, and resembles a snowflake. It is made by sticking together three copies of meeting each other at 60 angles so that they close up. We do this now:
>
KochFlake := proc(n::nonnegint)
ResetTurtle();
SetTurtleAngle(60);
cat(`L`,Koch(n),`RR`,Koch(n),`RR`,Koch(n));
end:
>
plots[display](array([[seq(TurtleCmd(KochFlake(i)),i=0..2)],
[seq(TurtleCmd(KochFlake(i)),i=3..5)]]));
What happens to the curve if we change the height of the bumps we add at each stage? We can do this easily by changing the angle the turtle turns when it encounters an R or an L. For example, an angle of 10 gives a curve which is nearly smooth.
>
ResetTurtle(); SetTurtleAngle(10);
TurtleCmd(Koch(6));
But an angle of 80 gives a curve which wiggles wildly and almost seems to take up area.
>
ResetTurtle(); SetTurtleAngle(80);
TurtleCmd(Koch(6));
We shall make this observation more precise in section 5. You might try some additional experiments on your own, to gain intuition about how the limit curve depends on the parameters. For example, what would happen if you make the angle be 90? Do you find the result surprising?
Some other variations you might want to try on your own might be to modify the
Koch
procedure so that the bumps are added alternately above and
below the curve, as shown in the following figure:
Here the angle used was less than 60. What happens for an angle of exactly 60? How about a larger angle? Can you adjust things so that using 75 angle does not cause self-intersections?
Or, you might try using a different shape of a bump. For example, below we used squares, shrinking the scale first so the bumps don't run into each other. What happens if you vary the scale factor with
SetTurtleScale
?