Monday, October 26th, 2026¶

Last week, we generated a checkerboard tartan and discusses some ideas for generating the authentic tartan pattern.

Next steps¶

  • The project asks you to produce a 500 by 500 tartan image based on your assigned pattern. The assigned pattern length is less than 500, so you will need to think about how to repeat the pattern enough times to fill in the full 500 by 500 image.
  • It would be good to create functions that perform the tasks of creating these various arrays. For example, a function get_vertical_stripes could take in the tartan recipe as inputs and return the corresponding vertical_stripes array. When it comes time to actually generate your assigned tartan, we can then just call upon these helper functions.
  • While we have made big improvements in how we generate the vertical_stripes array, there still was some amount of manual work on our part. Can we do better?

String processing¶

In generating our tartan images, we interpreted the tartan recipe by defining lists for the widths and colors. It would be nice if we could use Python to generate the list of widths and colors automatically. In other words, it would be convenient if we could define a string like tartan_recipe = 'B14 K6 B6 K6 B6 K32 OG32' and process this string to pull out these two lists.

In [1]:
tartan_recipe = 'B14 K6 B6 K6 B6 K32 OG32'

We have already seen some useful tools for working with strings in Python. For example:

  • The .join method allows us to concatenate a list of strings using a given string as a separator.
  • The .format method allows us to plug values into a string template.

Another helpful tool is the .split method, which allows us to separate a string into a list of substrings. The syntax is something like:

some_string.split(some_separator)

This will separate the some_string string into a list of substrings, where each separation occurs whenever the some_separator string is found within some_string.

In [2]:
my_string = "This is a sample string. We are in MTH 337."
In [3]:
my_string.split(' ')
Out[3]:
['This', 'is', 'a', 'sample', 'string.', 'We', 'are', 'in', 'MTH', '337.']
In [4]:
my_string.split('s')
Out[4]:
['Thi', ' i', ' a ', 'ample ', 'tring. We are in MTH 337.']
In [ ]:
 

Note: If we call the .split method with no input variable, by default the string will be split anywhere there is white space (e.g. spaces, tabs, line breaks, etc.).

In [5]:
my_string = "This is a     string with       a lot of    white space."
In [6]:
my_string.split(' ')
Out[6]:
['This',
 'is',
 'a',
 '',
 '',
 '',
 '',
 'string',
 'with',
 '',
 '',
 '',
 '',
 '',
 '',
 'a',
 'lot',
 'of',
 '',
 '',
 '',
 'white',
 'space.']
In [7]:
my_string.split()
Out[7]:
['This', 'is', 'a', 'string', 'with', 'a', 'lot', 'of', 'white', 'space.']

We can then apply the .split method to the tartan_recipe string to get a sequence of substrings, each of which represents a particular stripe.

In [8]:
print(tartan_recipe)
B14 K6 B6 K6 B6 K32 OG32
In [10]:
stripe_recipes = tartan_recipe.split()

Can we iterate through each of these stripe recipes and pick out the color and width?

In [11]:
stripe_recipe = stripe_recipes[0] # Get the first stripe recipe
print(stripe_recipe)
B14
In [12]:
stripe_recipe[0]
Out[12]:
'B'
In [13]:
stripe_recipe[1:]
Out[13]:
'14'

Problem: We can't just take the first character from stripe_recipe as the color code, because some color codes have two characters (e.g. 'OG').

It would be very helpful if we could pick out which parts of a string are letters and which parts of a string are numbers. The following methods (called on a string) can help with this:

  • The .isalpha method will return True if the string contains only alphabetic characters (i.e. letters).
  • The .isnumeric method will return True if the string contains only numeric characters (i.e. numbers).
In [14]:
s = 'This is a string with spaces and letters'
In [15]:
s.isalpha()
Out[15]:
False
In [18]:
word = s.split()[0]
print(word)
print(word.isalpha())
This
True
In [19]:
'123456'.isnumeric()
Out[19]:
True
In [20]:
'1a2b3c'.isnumeric()
Out[20]:
False
In [21]:
'one'.isnumeric()
Out[21]:
False

Exercise: Write a function that takes in a tartan recipe string and returns a list of color codes (e.g. ['B', 'K', 'B', ...]) and widths.

In [26]:
print(tartan_recipe)
stripe_recipes = tartan_recipe.split()

stripe_recipe = stripe_recipes[0]
print(stripe_recipe)

color_code = ''
for char in stripe_recipe:
    if char.isalpha():
        color_code += char

print(color_code)
B14 K6 B6 K6 B6 K32 OG32
B14
B
In [27]:
print(tartan_recipe)
stripe_recipes = tartan_recipe.split()

for stripe_recipe in stripe_recipes:
    color_code = ''
    for char in stripe_recipe:
        if char.isalpha():
            color_code += char
    
    print(color_code)
B14 K6 B6 K6 B6 K32 OG32
B
K
B
K
B
K
OG
In [29]:
print(tartan_recipe)
stripe_recipes = tartan_recipe.split()

color_codes = []
for stripe_recipe in stripe_recipes:
    color_code = ''
    for char in stripe_recipe:
        if char.isalpha():
            color_code += char
    
    color_codes.append(color_code)

print(color_codes)
B14 K6 B6 K6 B6 K32 OG32
['B', 'K', 'B', 'K', 'B', 'K', 'OG']
In [32]:
my_string = 'Hello, this is Jon Lottes. Today is Monday, October 26th, 2026'

print(my_string.split())
['Hello,', 'this', 'is', 'Jon', 'Lottes.', 'Today', 'is', 'Monday,', 'October', '26th,', '2026']
In [33]:
words_with_s = [word for word in my_string.split() if 's' in word]
print(words_with_s)
['this', 'is', 'Lottes.', 'is']
In [34]:
my_string = 'OG32'

for char in my_string:
    print(char)
O
G
3
2
In [35]:
for char in my_string:
    if char.isnumeric():
        print(char)
3
2

Exercise: Write a function that takes in a tartan recipe string and returns a list of color codes (e.g. ['B', 'K', 'B', ...]) and widths using list comprehensions.

In [ ]:
 
In [ ]:
 
In [ ]:
 

From the above, we can pick out the color code strings from the tartan recipe. On the other hand, in order to generate our vertical_stripes array, we need to get the corresponding RGB triples (not just the color code strings). How can accomplish this?

In [36]:
print(color_codes)
['B', 'K', 'B', 'K', 'B', 'K', 'OG']
In [37]:
colors = []

for color_code in color_codes:
    if color_code == 'B':
        colors.append([52/255, 80/255, 100/255])
    elif color_code == 'K':
        colors.append([16/255, 16/255, 16/255])
    elif color_code == 'OG':
        colors.append([92/255, 100/255, 40/255])
In [39]:
for color_code, color in zip(color_codes, colors):
    print(color_code, color)
B [0.20392156862745098, 0.3137254901960784, 0.39215686274509803]
K [0.06274509803921569, 0.06274509803921569, 0.06274509803921569]
B [0.20392156862745098, 0.3137254901960784, 0.39215686274509803]
K [0.06274509803921569, 0.06274509803921569, 0.06274509803921569]
B [0.20392156862745098, 0.3137254901960784, 0.39215686274509803]
K [0.06274509803921569, 0.06274509803921569, 0.06274509803921569]
OG [0.3607843137254902, 0.39215686274509803, 0.1568627450980392]

It would be convenient if we could define a mapping that maps each color code to its respective RGB triple.

Dictionaries¶

Let's consider a list, my_list.

In [40]:
my_list = ['Hello', 'World', 'Goodbye', 7]

We can think of my_list as a mapping between indices 0, 1, 2, 3, and values 'Hello', 'World', 'Goodbye', 7. That is, we have the following mappings:

  • index 0 maps to value 'Hello',
  • index 1 maps to value 'World',
  • index 2 maps to value 'Goodbye',
  • index 3 maps to value 7.

To retrieve values of a list, we can "plug in" an index using square brackets []:

In [41]:
my_list[0]
Out[41]:
'Hello'
In [42]:
my_list[1]
Out[42]:
'World'
In [43]:
my_list[2]
Out[43]:
'Goodbye'

A Python dictionary works very similarly, except that instead of a map from indices to values, we have a map from keys to values. These keys do not need to be integers 0, 1, 2, ..., but are more flexible. Dictionary keys can include integers, floats, strings, tuples, functions, and many other types (anything that is immutable).

To define a dictionary, we can use curly braces {} containing a comma-separated sequence of <key>:<value> mappings. For example, suppose we want to construct a dictionary with the following mappings:

  • key 5 maps to value 'Hello!',
  • key (0,255,0) maps to 'Green',
  • key 'Good' maps to value 10,
  • key 'Bad' maps to value 0,
  • key 'Red' maps to value (255,0,0).
In [44]:
my_dict = {5: 'Hello!', 
           (0,255,0): 'Green',
           'Good': 10,
           'Bad': 0,
           'Red': (255,0,0)}

Just like with lists, we can "plug in" a key to the dictionary and retrieve the corresponding value using square brackets [].

In [45]:
my_dict[5]
Out[45]:
'Hello!'
In [46]:
my_dict['Good']
Out[46]:
10
In [47]:
my_dict['Red']
Out[47]:
(255, 0, 0)
In [48]:
my_dict['Blue']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[48], line 1
----> 1 my_dict['Blue']

KeyError: 'Blue'

Note: unlike lists , we cannot use slicing with dictionaries. This is because the dictionaries do not have any inherent order in Python.

If desired, we can access the keys of a dictionary using the .keys method. Similarly, we can access the values using the .values method. Finally, we can access key/value pairs using the .items method. This allows us to iterate through dictionaries in several ways:

  • for key in my_dictionary.keys() will iterate through each key of the dictionary. We can also write for key in my_dictionary, which will still iterate through the keys.
  • for value in my_dictionary.values() will iterate through each value of the dictionary.
  • for key, value in my_dictionary.items() will iterate through each key/value pair.
In [49]:
for key in my_dict.keys():
    print(key)
5
(0, 255, 0)
Good
Bad
Red
In [50]:
for value in my_dict.values():
    print(value)
Hello!
Green
10
0
(255, 0, 0)
In [51]:
for key, value in my_dict.items():
    print(key, value)
5 Hello!
(0, 255, 0) Green
Good 10
Bad 0
Red (255, 0, 0)
In [ ]:
 
In [ ]:
 

Exercise: Write a dictionary whose keys are the color codes 'B', 'K', and 'OG' and whose values are the corresponding RGB triples.

In [52]:
color_dict = {'B': [52/255, 80/255, 100/255],
              'K': [16/255, 16/255, 16/255],
              'OG':[92/255, 100/255, 40/255]}
In [54]:
color_dict['B']
Out[54]:
[0.20392156862745098, 0.3137254901960784, 0.39215686274509803]

Exercise: Use the color_codes list and the above dictionary to construct a list colors containing the RGB triples for each stripe in the tartan recipe.

In [ ]:
 
In [ ]:
 
In [ ]: