Welcome back everyone! Today we’ll move away a bit from the usual coding problem challenges to look at something I used to play with when I started to learn to code. It’s a bit of a silly game really, but also a nice opportunity to explore some times tables math, coding and…turtles!
Ready? Let’s begin then.
Times tables are probably the first concept everyone learns at elementary school after basic arithmetic. I still remember my teacher’s method: she used to teach us by learning them by memory, and then we had small competitions in class. We were given a piece of paper with a table and some missing results and we had to fill all the times tables learnt up to that point: whoever finished first was given a prize. It was really funny, back in the days.
Besides being a tool for the every-day life and a school exercise though, if we take a closer look at times tables, we can discover that there is a lot more hidden behind them.
For example: what happens if we try to draw them?
The idea behind this little program came to me by a video by Prof. Polster, who runs the brilliant YT channel Mathologer. You can take a look at his content here: he delves a lot more into the concept, talking about Mandelbrot sets and Riemann Z function and he’s just way too good at explaining those concepts in a fun and easy to understand way.
We will limit our game to the pictures of the times tables tough, specifically writing some code that will draw them for us.
The idea is pretty simple: we draw a circle first, and we enumerate some points on the circumference, leaving the same distance between them. After that we start calculating the results for a given times table and connect the results. For example, for the 6-times table:
and so on. What happens if we connect a greater number of points? Let’s find out.
Before starting, a quick refresh about the concepts we are going to see here. A circumference is the set of the points equidistant from its center, also called origin (O). That distance is called radius (r).
On the plane, assuming we have our origin point O with coordinate x and y, we can find the coordinates of the point A on the circumference with the following equations:
where θ is the angle created by the point A, the origin and the y axis of the plane, adjusted by the x and y coordinates. For example, this circle has O in (4,4) and r = 3. The point A is drawn on its circumference, creating an angle a of 30°. We can calculate the coordinates of A like
You can verify with the drawing below.
Another important concept is the difference between degrees and radian:
Without going too deep, we can calculate the Rad by the following equation:
We’ll also use a bit of modular arithmetic to calculate our results on the circle. Simply put, the modulo operator gives us the remainder of a division: for instance, A%B = C (red as “A modulo B equals C”), will mean that the remainder of A/B equals C.
That’s enough info for our mission today. We’ll make wide use of these concepts below so check them out carefully.
Now for the fun part, let’s start drawing!
When I started learning Python, I used to play a lot with this library, turtle, which is a great tool to draw shapes and geometries. It’s often skipped while learning the language, mainly because it has no real purpose and it’s usage is really limited. However I think it’s a great library, well documented and easy to use, which is really worthy to explore and have fun with.
The library is really simple: we will “spawn” a turtle (which we’ll call Bob, as it’s often named in tutorials around the web), represented by an arrow on the screen, and move it giving directions and turning points. Here’s an example of some basic commands:
import turtle
bob = turtle.Turtle()
bob.fd(50) # Go 50 pts forwars
bob.left(90) # Turn 90° left
bob.back(50) # Go 50 pts backwards
bob.right(90) # Turn 90° right
bob.pensize(2) # Change line size
bob.pencolor("red") # Change line color
bob.fd(50)
bob.left(90)
bob.fd(100)
bob.pensize(3)
bob.pencolor("green")
bob.left(90)
bob.fd(100)
turtle.mainloop()
Let’s start drawing then!
First we define the function drawCircle
which accepts the following parameters:
turtle, the turtle we are moving;
radius, the radius of the circle;
origin, the origin of the circle given as a tuple of coordinates x and y, set by default on (0,0);
penSize, penColor and writeLabel, which are graphics parameters to set the line width, color and the label on the origin
Notice that turtle starts drawing from the lowest point of the circumference, so the function just moves the turtle down by the radius length, draws the circle and then moves back up by the radius.
We first need to decide how many points to add on the circle. Let’s start simple and try with 12, like on the clock! We need to put 12 points on the circle, with the same distance between one another.
Knowing that the angle of a full circular rotation it’s 360°, we can simply split this rotation in 12 parts and get an angle of 360°/12 = 30° for each point. Also, we’ll be working with math.sin
and math.cos
from the Python math
library, which use radians as measure, so it’s better to convert our angle right now. Let’s write a function to wrap this up:
And now let’s put the points on the circle:
We define the function drawCircumferencePoints
, that accepts the usual parameters and a new one, coordinates
, which is a dictionary to collect the points and their coordinates. This way we can avoid recalculating all the points in the next step, which comes really in handy while working with greater numbers of points.
The inner function singlePointDraw
simply moves the turtle to the coordinates for a given angle
and places a dot.
With this function, we range over our points and drop a point with singlePointDraw
: the angle will always be 30°, so for each point in the range we drop a point at i*angle
: for point 0 we’ll place it at 0*30° = 0°
, for point 1 at 1*30° = 30°
, for point 2 at 2*30° = 60°
and so on.
At this point we also collect the position of our turtle and the angle in the coordinates
dictionary. It’s not really necessary to collect the angle: I used it for testing and left it there (unintentionally ;D)!
Finally, if the parameter writeLabel
is set to True
, we’ll write the point number aside each point.
Calling drawCircle
and drawCircumferencePoints
you should now have something like this:
Also note that the points start at 0 and end at 11: this is why modular arithmetic will come in help pretty soon.
At last, let’s put down our times-table! Let’s pick the number 3, for example, and draw it’s time table.
We define another function to do this, drawTable
. After that we calculate the base angle to have a reference in this function and store it in the variable angle
.
Then, we start looping over our points. For each point we define:
a starting point, taken from the coordinates we listed before;
an end point, calculated as the value of the starting point multiplied by the chosen times table.
This is where the modulo operator comes in action: multiplying, for example, 3 * 11 gives 33 as result, so we should move to point 33 on the circle. We have only 12 points on the circle, though, so we can use the modulo to calculate 33%12 = 9, which is exactly the point we end up on if we go around the circle 33 times.
Finally, we simply draw a line between the starting dot and the end dot, and start the loop again with the next number.
At this point, you should have something like this:
Let’s wrap up all the code in a single function:
This function basically calls the other function created above in the right order, nothing more really. It adds the parameter speed
to set the speed of the turtle, so we can control how fast the animation is (trying with higher number of points takes a bit of time!). It also holds the variable coordinates
, which was outside the drawCircle
function before, and now it’s contained by the outertimesTablesDrawer
function.
The image resulting with the number 3 was ok, but not that much of a masterpiece: it was just a bunch of lines inside a circle. That is because there are too few points on the circle. Let’s try adding some more: 200 points for example!
That’s way more cute! How strange is the shape drawn, right?
These types of curves are called cardioids, for their shape remembering a heart. It’s pretty clear if you look at the one in the cover image, which is the 2-times table cardioid. Generally speaking, these kind of shapes has a number of “bumps” equal to the chosen times-table minus one: in this example, the time table was 3 and in fact the image has 2 round bumpy shapes in it.
These cardioids pop up a little everywhere around math, physics, chemistry and nature. In microphones and apples, for example…and also in your cup of tea!
And there is more! If we try to draw higher times-tables, we can see tons of different shapes coming up: some of them has nothing to do with cardioids, like the 99 or the 66 times-table!
Here some examples with greater numbers:
Give it a try with different number of points and times-tables: I can assure you it’s so much fun to look at the little turtle running around to draw beautiful shapes!
We can also draw intermediate results, meaning times-tables with decimal places. It’s also really cool to see intermediate results because it gives us an idea about how the image gets created and changes from one result to another. Here’s an animation of the times-tables from 2 to 3 (sorry for the bad quality!):
You can see how the shape basically keeps rotating and enveloping on itself, almost shifting to the left, to create the next cardioid. How awesome!
That’s it! A long journey (as most of the times here). It’s a bit different from the usual articles about coding problems solving, but I recently saw that video again and it instantly made me want to share my try to it.
I also wrote a simple program to draw these shapes, you can download it from my Github page, here (click on ‘Raw’ to download it!): feel free to use it whenever and wherever you like.
I hope you enjoyed it and find it interesting! If you did, please leave a clap or two or share it with someone who could enjoy it too: it would make my day!
As always, thanks for reading.
Nicola