Exercises#

Q 1 (function practice)#

Let’s practice functions. Here’s a simple function that takes a string and returns a list of all the 4 letter words:

def four_letter_words(message):
    words = message.split()
    four_letters = [w for w in words if len(w) == 4]
    return four_letters
message = "The quick brown fox jumps over the lazy dog"
print(four_letter_words(message))
['over', 'lazy']

Write a version of this function that takes a second argument, n, that is the word length we want to search for

Q 2 (primes)#

A prime number is divisible only by 1 and itself. We want to write a function that takes a positive integer, n, and finds all of the primes up to that number.

A simple (although not very fast) way to find the primes is to start at 1, and build a list of primes by checking if the current number is divisible by any of the previously found primes. If it is not divisible by any earlier primes, then it is a prime.

The modulus operator, % could be helpful here.

Q 3 (exceptions for error handling)#

We want to safely convert a string into a float, int, or leave it as a string, depending on its contents. As we’ve already seen, python provides float() and int() functions for this:

a = "2.0"
b = float(a)
print(b, type(b))
2.0 <class 'float'>

But these throw exceptions if the conversion is not possible

a = "this is a string"
b = float(a)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[4], line 2
      1 a = "this is a string"
----> 2 b = float(a)

ValueError: could not convert string to float: 'this is a string'
a = "1.2345"
b = int(a)
print(b, type(b))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[5], line 2
      1 a = "1.2345"
----> 2 b = int(a)
      3 print(b, type(b))

ValueError: invalid literal for int() with base 10: '1.2345'
b = float(a)
print(b, type(b))
1.2345 <class 'float'>

Notice that an int can be converted to a float, but if you convert a float to an int, you rise losing significant digits. A string cannot be converted to either.

your task#

Write a function, convert_type(a) that takes a string a, and converts it to a float if it is a number with a decimal point, an int if it is an integer, or leaves it as a string otherwise, and returns the result. You’ll want to use exceptions to prevent the code from aborting.

Q 4 (tic-tac-toe)#

Here we’ll write a simple tic-tac-toe game that 2 players can play. First we’ll create a string that represents our game board:

board = """
 {s1:^3} | {s2:^3} | {s3:^3}
-----+-----+-----
 {s4:^3} | {s5:^3} | {s6:^3}
-----+-----+-----      123
 {s7:^3} | {s8:^3} | {s9:^3}       456
                       789  
"""

This board will look a little funny if we just print it—the spacing is set to look right when we replace the {} with x or o

print(board)
 {s1:^3} | {s2:^3} | {s3:^3}
-----+-----+-----
 {s4:^3} | {s5:^3} | {s6:^3}
-----+-----+-----      123
 {s7:^3} | {s8:^3} | {s9:^3}       456
                       789  

and well use a dictionary to denote the status of each square, “x”, “o”, or empty, “”

play = {}

def initialize_board(play):
    for n in range(9):
        play[f"s{n+1}"] = ""

initialize_board(play)
play
{'s1': '',
 's2': '',
 's3': '',
 's4': '',
 's5': '',
 's6': '',
 's7': '',
 's8': '',
 's9': ''}

Note that our {} placeholders in the board string have identifiers (the numbers in the {}). We can use these to match the variables we want to print to the placeholder in the string, regardless of the order in the format()

a = "{s1:} {s2:}".format(s2=1, s1=2)
a
'2 1'

Here’s an easy way to add the values of our dictionary to the appropriate squares in our game board. First note that each of the {} is labeled with a number that matches the keys in our dictionary. Python provides a way to unpack a dictionary into labeled arguments, using **

This lets us to write a function to show the tic-tac-toe board.

def show_board(play):
    """ display the playing board.  We take a dictionary with the current state of the board
    We rely on the board string to be a global variable"""
    print(board.format(**play))
    
show_board(play)
     |     |    
-----+-----+-----
     |     |    
-----+-----+-----      123
     |     |           456
                       789  

Now we need a function that asks a player for a move:

def get_move(n, xo, play):
    """ ask the current player, n, to make a move -- make sure the square was not 
        already played.  xo is a string of the character (x or o) we will place in
        the desired square """
    valid_move = False
    while not valid_move:
        idx = input(f"player {n}, enter your move (1-9)")
        if play[f"s{idx}"] == "":
            valid_move = True
        else:
            print("invalid move")
            
    play[f"s{idx}"] = xo
help(get_move)
Help on function get_move in module __main__:

get_move(n, xo, play)
    ask the current player, n, to make a move -- make sure the square was not 
    already played.  xo is a string of the character (x or o) we will place in
    the desired square

your task#

Using the functions defined above,

  • initialize_board()

  • show_board()

  • get_move()

fill in the function play_game() below to complete the game, asking for the moves one at a time, alternating between player 1 and 2

def play_game():
    """ play a game of tic-tac-toe """
    
    play ={}
    initialize_board(play)
    show_board(play)
play_game()
     |     |    
-----+-----+-----
     |     |    
-----+-----+-----      123
     |     |           456
                       789