Recently I did a few interesting things with modulo. I had a turtle script, where I build up (more than) all the guides and intersections from the vesica piscis to lay out the pentagram, but as yet I am not programmatically fetching intersection points. I guess that's a major goal. Anyway, I had one point on the circle, the top one, and I said, from here, I can use angle and length, (for the radius of one of the circles I drew was just what I needed) and I divided 360 by 5, and drew a pentagon with a for loop.
I said, while I have the turtle at each corner I can capture the location and save it in a list, so I did. Then I said, now I can have the turtle traverse these points with turtle.goto(), but then I needed a way to skip steps, and run over the list again with a different key, and avoid out of range errors.
So, when you use a for loop to iterate through a list you go in order. There are ways to specify steps, so you can easily process every other list item, and in python it is easy to go over a list in reverse, but to skip every other point, and still visit them all was not at first clear. I thought it was a simple concept and ought to be done elegantly, but it took some thinking. Also, this is a general trend with stars from regular polygons. You often get different stars if you skip a different number of points, so I thought it was worth thinking of a method that would be flexible.
The basis of this method was the modulo operator. This is one of the basic math operations along with addition, subtraction, multiplication and division, it is mostly of use with integers. The utility of modulo in this case is that it gives a cyclic result when given a linear input. That is, if you have a list of 5 items, then you iterate over it by adding 1 in every cycle, and your result comes out as: 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0...
So, in a list with an odd number of items, you can go over the list and pick every even numbered item and then just repeat the list and pick the ones you missed the first time. There's an off-by one problem too though, because to close the star I have to revisit the first point again, so it is [points[(i * 2) % 5] for i in range(6)]:
so I have six iterations in a five point list, or even in a six point list, because with mod 5 it doesn't matter if my first point is repeated at the end or not.
Lets look at how this works. I write a standard for loop:
for i in [points[(i * 2) % 5] for i in range(6)]:
turtle.goto(i)
And the result of this will be, for i generated, and modified i passed to turtle each iteration:
0,0
1,2
2,4
3,1
4,3
5,0
loop complete.
I then tried this on an 8 pointed star, with a range of 9. With skip 1 the turtle goes over a square twice, because a skip 1 star with 8 points is two separate squares, not a unicursal figure, as the pentagram is, but with skip 2, I got the 8-pointed star that fans of Full Metal Alchemist will be familiar with.
There are two unicursal stars with 7 points though, one which may be familiar from the seals of Sheriffs, another that may be recognizable from Game of Thrones. (Also an ancient symbol of wisdom and the planetary gods.) And I believe there are multiple 9 pointed stars as well.
The use of the modulo for cyclic output is actually pretty common in early programming exercises. For instance, some of beginner graphics programs use it with a list of colors to add variety, and I did a code-wars challenge a while back where I implemented a secret decoder ring for the rot 13 code with an alphabet string and mod 26. You can set your decoder ring to any offset you need to, not just 13.
Yet, I don't recall seeing the modulo operator in my youth. When I was a kid and playing with Vic 20 BASIC, I hoped that I could get the computer to do my math homework for me, for I found it tedious and unpleasant. But my homework at that time involved division with remainders. And when you do those operations with a computer or a calculator you typically get a decimal answer, which was not what was called for. If I have a litter of six kittens and want to give one away to each of five friends and see how many I have left over it does no good to say that everyone gets 1.2 kittens. Even if I were dividing sandwiches, how do you cut a sandwich into exact fifths? It seems that if I had known of the modulo then, I could have used it. Many programming languages have a divmod()
function, or with modulo you can write one, and that was what I wanted.
I recently perused the Vic 20 programming manual again. I found them as pdfs on the internet archive, and I have to say that I am a little surprised about how similar it is to using Python today. There are obviously major differences, the first being that the flow of the program in BASIC depended on explicit line numbers, and often explicit instructions to shift to a part of the program that began on a different line number. For instance: 70 IF A$ = "YES" THEN GOTO 30
thus you create loops and specify subroutines like directing a reader through a choose your own adventure book. But in the modern languages I've tried, like Java and Python, it is surprising how the flow of execution is sort of implied and freeform, with no explicit line numbers, though you use them for debugging. On the other hand, the basic constructs are all still there, variables, functions, loops, decisions, input etc. But I didn't find the modulo operator among the math functions in the Vic 20's beginner manual. Yet it was one of the first things covered in Java and Python. Apparently, a modulo operator was not a standard part of BASIC in the 1980s, and to use it you would have had to define it like this:
a - int(a/b) * b
In this case we are using type casting, with the int()
function, but it may make sense to use floor division //
depending on what programming language you are using. I forget the details of Commodore BASIC, but surely if a variable is defined as an integer it cannot contain a decimal part, and that will be discarded. In any case the operation works.