There are times when we want to create a pattern where we vary the color in a predetermined sequence. For example, take a look at the pattern below.
This pattern consists of the following color sequence: green, blue, red, cyan, purple, white, and yellow. There are different ways to go about doing this. We’ll discuss two approaches. In both approaches we will put all of the color in to a colors
array and then select the colors from there. The first approach does this selection using a color_index
variable as shown below.
from wc import *
canvas = Canvas()
colors = [ 'green', 'blue', 'red', 'cyan', 'purple', 'white', 'yellow' ]
color_index = 0
points = []
for y in range(canvas.height):
for x in range(canvas.width):
points.append(Point(x,y,colors[color_index]))
color_index += 1
if (color_index > 6):
color_index = 0
canvas.add(points)
What is happening in this logic is that the color index is increasing in value from 0 until it reaches 6 at which point it resets. This means the value cycles in this manner: 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1,
etc… One improvement we can make here is to replace 6
with len(colors
)-1
as shown below.
from wc import *
canvas = Canvas()
colors = [ 'green', 'blue', 'red', 'cyan', 'purple', 'white', 'yellow' ]
color_index = 0
points = []
for y in range(canvas.height):
for x in range(canvas.width):
points.append(Point(x,y,colors[color_index]))
color_index += 1
if (color_index > len(colors) - 1):
color_index = 0
canvas.add(points)
While this approach works, it results in a lot of messy code around the management of the color index. It turns out there is a very efficient way to do this with something called the modulus operator.
Modulus Operator
The modulus operator uses the percent sign character %. It is basically a remainder function. Take a look at the examples below to get the idea of what it does.
Expression | Result |
---|---|
5%2 | 1 |
8%3 | 2 |
9%3 | 0 |
14%5 | 4 |
9%7 | 2 |
You might be wondering how we would use this to solve our color index problem. Take a look at these additional examples of the modulus operator in action and perhaps you’ll see the connection.
Expression | Result | Expression | Result |
---|---|---|---|
0%7 | 0 | 7%7 | 0 |
1%7 | 1 | 8%7 | 1 |
2%7 | 2 | 9%7 | 2 |
3%7 | 3 | 10%7 | 3 |
4%7 | 4 | 11%7 | 4 |
5%7 | 5 | 12%7 | 5 |
6%7 | 6 | 13%7 | 6 |
Remember that our goal is to have the color index cycle through the values 0-6 repeatedly as we progress through the for-loop. Well it turns out that’s exactly the result we get when we use the modulus operator. So with that explanation, take a look at the code below and see if it makes sense to you.
from wc import *
canvas = Canvas()
colors = [ 'green', 'blue', 'red', 'cyan', 'purple', 'white', 'yellow' ]
color_index = 0
points = []
for y in range(canvas.height):
for x in range(canvas.width):
pixel_num = y * 16 + x
points.append(Point(x,y,colors[pixel_num%len(colors)]))
canvas.add(points)
Notice that we don’t even need a color index variable anymore. This results in much less cluttered code.
Challenge Problem
Now let’s leverage what we learned about the modulus operator to do something more ambitious. Let’s define a pattern of lines that cycle through a predetermined list of colors and line lengths. Look at the image below and see if you can determine the repeating pattern.
The pattern is outlined in the table below.
Color | Length |
---|---|
Green | 2 |
Blue | 6 |
Red | 3 |
Cyan | 9 |
Purple | 5 |
White | 7 |
Yellow | 4 |
So how do we go about doing this? The approach taken below is to store the colors and lengths in two arrays (lines 4-5) and then track how long we have been painting a line with a certain color using a for range loop (line 12). Once we have completed the required repetitions we cycle to the next set of color (lines 20-22) and length values. We use a conditional (line 15) to test when we have reached the end of a row and advance to the next row (line 17) while resetting the column index to zero (line 16).
from wc import *
canvas = Canvas()
colors = [ 'green', 'blue', 'red', 'cyan', 'purple', 'white', 'yellow' ]
lengths = ( 2, 6, 3, 9, 5, 7, 4 )
color_index = 0
points = []
x = 0
y = 0
color_index = 0
while y < canvas.height:
for count in range(lengths[color_index]):
points.append(Point(x,y,colors[color_index]))
x += 1
if x == canvas.width:
x = 0
y += 1
if y == canvas.height:
break
color_index += 1
if (color_index == len(colors)):
color_index = 0
canvas.add(points)
We can make this code even better by combining the sets of color and length values into a single set which has tuples of values. This makes the code more compact and also easier to follow.
from wc import *
canvas = Canvas()
colors = ( ('green',2), ('blue',6), ('red',3), ('cyan',9), ('purple',5), ('white',7), ('yellow',4) )
color_index = 0
points = []
x = 0
y = 0
color_index = 0
while y < canvas.height:
for count in range(colors[color_index][1]):
points.append(Point(x,y,colors[color_index][0]))
x += 1
if x == canvas.width:
x = 0
y += 1
if y == canvas.height:
break
color_index += 1
if (color_index == len(colors)):
color_index = 0
canvas.add(points)
No responses yet