8c. Prof. Rosenthal’s Review#

A review of Chapter 8: Strings and Regular Expressions, for students who have already studied the chapter. Use the two lists under Concepts covered as a checklist (click a list’s title to hide it), then work through the Questions, which go from easy to hard. Each question has a suggested answer under Answer. Try the question first, then open the Answer.

Run this page on Colab

Concepts covered#

Questions#

The questions use indexing and slices, string methods, files, break and regular expressions. The module re (regular expressions) is imported in the setup cell below with import re.

One question reads words.txt, a list of about 114,000 English words, one per line, in alphabetical order (the first two are aa and aah). The setup cell below downloads it.

from os.path import basename, exists

def download(url):
    filename = basename(url)
    if not exists(filename):
        from urllib.request import urlretrieve

        local, _ = urlretrieve(url, filename)
        print("Downloaded " + str(local))
    return filename

download('https://raw.githubusercontent.com/AllenDowney/ThinkPython/v3/words.txt');

import re

Summary and questions by Prof. Y. Rosenthal, based on Think Python: 3rd Edition by Allen B. Downey. Text license: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International

Question 1 (easy): what is displayed?#

Predict what this code displays, then open the Answer to check.

fruit = 'banana'
print(fruit[0], fruit[1], fruit[5])
print(fruit[-1], fruit[-2])
print(len(fruit), fruit[len(fruit) - 1])

Question 2 (easy): what is displayed?#

word = 'Python'
print(word[0:2], word[2:4], word[4:6])
print(word[:2], word[2:])
print(word[:])
print('[' + word[3:3] + ']', len(word[3:3]))

Question 3 (easy): what is displayed?#

s = 'banana'
print(s.upper(), s)
print(s.startswith('ban'), s.startswith('Ban'), s.endswith('na'))
print(s.count('a'), s.count('n'), s.count('an'))
print(s.replace('a', 'o'), s.replace('an', ''))

Question 4 (easy): write a function#

Write a function called capitalize_first that takes a string word and returns a new string: the same as word, but with the first letter in uppercase.

Start from this header (replace ... with the body):

def capitalize_first(word):
    ...

Examples

print(capitalize_first('hello'))
Hello
print(capitalize_first('python'), capitalize_first('Already'))
Python Already

Question 5 (easy): what is displayed?#

print('apple' < 'banana', 'cherry' < 'banana')
print('Zebra' < 'apple', 'zebra' < 'apple')
print('ban' < 'banana', 'cat' == 'Cat', 'cat' == 'Cat'.lower())

Question 6 (medium): what happens?#

For each part, predict what happens: does it display something, or is it an error? Then open the Answer to check.

Part a

fruit = 'banana'
print(fruit[6])

Part b

fruit = 'banana'
print(fruit[6 / 2])

Part c

greeting = 'Hello'
greeting[0] = 'J'

Part d

fruit = 'banana'
print(fruit[2:100])

Question 7 (medium): what is displayed?#

greeting = 'Hello, world!'
new_greeting = 'J' + greeting[1:]
greeting.replace('world', 'Python')
shout = greeting.upper()
print(new_greeting)
print(greeting)
print(shout)

Question 8 (medium): what is displayed?#

word = 'stop'
for i in range(len(word)):
    print(i, word[i], word[-1 - i], word[i:])

Question 9 (medium): write a function#

Write a function called rotate that takes a string word and an integer n from 0 to len(word), and returns a new string: the same letters, with the first n letters moved to the end.

Start from this header (replace ... with the body):

def rotate(word, n):
    ...

Examples

print(rotate('python', 2))
thonpy
print(rotate('banana', 1), rotate('abc', 0), rotate('abc', 3))
ananab abc abc

Question 10 (medium): write a function#

Write a function called censor that takes two strings, text and word, and returns a new string: the same as text, but with each occurrence of word replaced by as many * characters as word has letters.

Start from this header (replace ... with the body):

def censor(text, word):
    ...

Examples

print(censor('the darn cat is darn cute', 'darn'))
the **** cat is **** cute
print(censor('banana', 'an'))
print(censor('banana', 'x'))
b****a
banana

Question 11 (medium): what is displayed?#

for letter in 'programming':
    if letter == 'g':
        break
    print(letter, end=' ')
print()
print('stopped at', letter)

Question 12 (medium): what is displayed?#

writer = open('notes.txt', 'w')
writer.write('one\n')
writer.write('two ')
writer.write('three\n')
writer.write('four\n')
writer.close()

count = 0
for line in open('notes.txt'):
    count += 1
    print(count, line.strip())

Question 13 (medium): what is displayed?#

re is the module for regular expressions; it was imported with import re.

text = 'I am Dracula; and I bid you welcome.'
result = re.search('Dracula', text)
print(result.group())
print(result.span())
print(text[5:12])
print(re.search('Count', text))

Question 14 (medium): write a function#

Write a function called reverse that takes a string and returns a new string with the same characters in reverse order.

Start from this header (replace ... with the body):

def reverse(word):
    ...

Examples

print(reverse('stressed'))
desserts
print(reverse('abc'), reverse('a'), '[' + reverse('') + ']')
cba a []

Question 15 (hard): what is displayed?#

The function has_match returns True if the regular expression pattern matches some part of text, and False otherwise (re is the module for regular expressions; it was imported with import re).

Run this cell to define has_match.

def has_match(pattern, text):
    return re.search(pattern, text) != None

Predict what this code displays:

print(has_match('cat|dog', 'hotdog'), has_match('^dog', 'hotdog'), has_match('dog$', 'hotdog'))
print(has_match('^hot$', 'hotdog'), has_match('^hotdog$', 'hotdog'))
print(has_match('colou?r', 'color'), has_match('colou?r', 'colouur'))
print(has_match('cent(er|re)', 'recent'), has_match('center|re', 'recent'))

Question 16 (hard): what is displayed?#

re is the module for regular expressions; it was imported with import re.

text = 'My favourite colour is the colour of the sea.'
print(re.sub('colou?r', 'color', text))
print(re.sub('favou?rite', 'favorite', text))
print(re.sub('^My', 'Your', text))
print(re.sub('sea$', 'sky', text))
print(text)

Question 17 (hard): what is displayed?#

writer = open('story.txt', 'w')
writer.write('Title\n*** START\nOnce upon a time\nThe end\n*** END\nLicense\n')
writer.close()

reader = open('story.txt')
for line in reader:
    if line.startswith('*** '):
        break
for line in reader:
    if line.startswith('*** '):
        break
    print(line.strip())
print(line.strip())
reader.close()

Question 18 (hard): write a function#

A palindrome is a word that reads the same backward and forward, such as racecar. Write a function called is_palindrome that takes a string and returns True if it is a palindrome and False otherwise. Uppercase and lowercase letters count as the same letter.

Start from this header (replace ... with the body):

def is_palindrome(word):
    ...

Examples

print(is_palindrome('racecar'), is_palindrome('Noon'))
True True
print(is_palindrome('python'), is_palindrome('a'), is_palindrome(''))
False True True

Question 19 (hard): write a function#

Write a function called count_words that takes a regular expression pattern and returns the number of words in the file words.txt that the pattern matches. words.txt has one word per line, in lowercase.

Start from this header (replace ... with the body):

def count_words(pattern):
    ...

Examples

print(count_words('^q'), count_words('ology$'))
568 100
print(count_words('^(un|re)'), count_words('colou?r'))
6614 57

This question uses has_match from Question 15.

Question 20 (hard): write a function#

Write a function called wordle_feedback that takes two strings of the same length, target and guess, and returns a string with one character for each letter of guess: G if the letter is at the same position in target, Y if it is somewhere else in target, and - if it is not in target.

Start from this header (replace ... with the body):

def wordle_feedback(target, guess):
    ...

Examples

print(wordle_feedback('mower', 'tried'))
-Y-G-
print(wordle_feedback('spade', 'spade'), wordle_feedback('spade', 'clerk'))
GGGGG --Y--

By the way: this is the information that the word game Wordle gives after each guess. (The real game handles letters that appear twice in a different way.)

Summary and questions by Prof. Y. Rosenthal, based on Think Python: 3rd Edition by Allen B. Downey. Text license: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International