This assignment will be closed on March 19, 2025 (23:59:59).
You must be authenticated to submit your files

Pale Machine CSE101, Groups 1-4

G. Pogudin

Objectives

What we will evaluate today: Everything!

Setup: Before you start

Launch Spyder (from the Applications/Programming menu). If you see a “Spyder update” message, just click OK and ignore it.

Before you start: create a new project, called PracticalExam_1 (using “New Project” from the “Projects” menu). This will ensure that files from last week (and future weeks) do not get mixed up together. Download files dict1.txt and dict2.txt from Moodle and put them in the project folder.

Now create a new file named wordgame.py. This is the file in which you will be writing your code today.

Introduction

In this exam you will implement the following word game. The game starts with a fixed relatively long word, for example, mathematics. Then, at each step, the player tries to come up with a word which can be constructed using the letters from the original word in any order. Note that each letter can appear in a new word at most as many times as it appears in the original word. For mathematics, possible words include tea, cat, cast, ham, etc. For each word, the player gets the number of points equal to the length of the word. Once the player gives up, the total score is counted.

Exercises

Exercise 1: Is this a word?

We start with a function which checks if a given word is “allowed” by looking this word up in a provided dictionary (represented as a list of words). We define a function is_in_dictionary which takes two arguments:

  • word is a word to look up;
  • dictionary is a list of “allowed” words.

The function should return True if the word appears in the dictionary and False otherwise. The comparison is assumed to be case-sensive, that is, cat is not the same as CaT.

Copy the following function stub into your file and complete it:

def is_in_dictionary(word, dictionary):
    """checks if the word appears in the dictionary 
    """
    pass  # remove this line and replace with your own code

Testing

Test your function is_in_dictionary() in the console, for example as follows:

In [1]: is_in_dictionary("cat", ["dog", "cat", "cow"])
Out[1]: True

In [2]: is_in_dictionary("cat", ["dog", "catastrophy", "cow"])
Out[2]: False

In [3]: is_in_dictionary("COW", ["dog", "catastrophy", "cow"])
Out[3]: False

Note: It is important to test your function in the console as there is no grader feedback.

Upload form is only available when connected

Exercise 2: Reading dictionary from file

Of course, it is not interesting to play with a dictionary like ["dog", "cat", "cow"], and it is definitely tedious to type an actual dictionary by hand. The goal of the exercise is to create a function read_dictionary(filename) reading a dictionary from file filename. The file filename is assumed to have at most one word per line (with possibly starting and trailing empty spaces) as well as empty lines. The words are guaranteed to be distinct. The function should return a list containing all the words. Here is the starter code:

def read_dictionary(filename):
    """Reads a dictionary from file.
    """
    pass  # remove this line and replace with your own code

Testing

When you have finished your function, test it in the console. You should see the following behavior:

In [4]: read_dictionary("dict1.txt")
Out[4]: ['dog', 'cat', 'cow']

In [5]: read_dictionary("dict2.txt")[:5]
Out[5]: ['people', 'history', 'way', 'art', 'world']
Upload form is only available when connected

Exercise 3: Checking if a word is constructable

Now we would like to check if a given word can be constructed using the letters of our original word. This will be done by a function is_constructable(target, source), where target and source are words. The function should return True if target can be constructed using the letters of source and False otherwise. Here is the starter code:

def is_constructable(target, source):
    """Checks if the word target can be constructed from the letters of 
    the word source.
    """
    pass  # remove this line and replace with your own code

Hint

You may want to use the count method which may be familiar from TD2 (try "mama".count('m') and "abaca".count('c')).

Testing

When you have finished your function is_constructable, test it in the console. You should be able to reproduce the following behavior:

In [6]: is_constructable("cat", "mathematics")
Out[6]: True

In [7]: is_constructable("catch", "mathematics")
Out[7]: False

In [8]: is_constructable("mamama", "mathematics")
Out[8]: False

In [9]: is_constructable("ratio", "algorithm")
Out[9]: True
Upload form is only available when connected

Exercise 4: Playing one round

Now we will write a function one_round() for playing one round of the game which takes 3 parameters:

  • mainword is a word from which the other words should be constructed;
  • found is a list of words (already found by the player);
  • dictionary is a dictionary.

The function should prompt the player Please construct a new word from the letters of the word _mainword_:. Once the player types the word, one of the following should happen:

  • if the player types ! (meaning he/she wants to stop the game), the function should return -1;
  • if the player types a word equal to mainword, the function should print Let's try something more interesting! and return 0;
  • if the player types a word which is not present in the dictionary, the function should print I do not know this word! and return 0;
  • if the player types a word already present in found, the function should print You have already found this word! and return 0;
  • if the player types a word which cannot be constructed from the letters of the mainword, the function should print Not enough letters! and return 0;
  • if the player types a word which can be constructed, is present in the dictionary, and had not been found before, the function should print Good job, you have earned # points, where # is the length of the word; the function should return the length of the found word in this case.

Do not forget to update the found list!

def one_round(mainword, found, dictionary):
    """plays one round of the game
    """
    pass  # remove this line and replace with your own code

Testing

Now, test your function one_round() in the console, for example as follows.

In [10]: dictionary = read_dictionary("dict2.txt")

In [11]: found = []

In [12]: one_round("mathematics", found, dictionary)

Please construct a new word from the letters of the word mathematics:cat
Good job, you have earned 3 points

Out[12]: 3

In [13]: one_round("mathematics", found, dictionary)

Please construct a new word from the letters of the word mathematics:cat
You have already found this word!

Out[13]: 0

In [14]: one_round("mathematics", found, dictionary)

Please construct a new word from the letters of the word mathematics:math
Good job, you have earned 4 points

Out[14]: 4

In [15]: one_round("mathematics", found, dictionary)
Please construct a new word from the letters of the word mathematics:abracadabra
I do not know this word!

Out[15]: 0

In [16]: found = []

In [17]:  one_round("algorithm", found, dictionary)
Please construct a new word from the letters of the word algorithm:algorithm
Let's try something more interesting!

Out[17]: 0

In [18]:  one_round("algorithm", found, dictionary)
Please construct a new word from the letters of the word algorithm:!

Out[18]: -1
Upload form is only available when connected

Exercise 5: Playing the game!

Now we use the one_round() function to write a play_game() function which takes mainword and dictionary as arguments. It should ask the player for a new word until the player types ! thus choosing to stop. Once the game is stopped, the function should print: You have constructed: followed by a comma-separated list of constructed words and Total score: followed by the total score.

def play_game(mainword, dictionary):
    pass  # remove this line and replace with your own code

Testing

When you have finished your function play_game, test it in the console. You should be able to reproduce the following behavior:

In [19]: dictionary = read_dictionary("dict2.txt")

In [20]: play_game("mathematics", dictionary)

Please construct a new word from the letters of the word mathematics:math
Good job, you have earned 4 points
Please construct a new word from the letters of the word mathematics:cat
Good job, you have earned 3 points
Please construct a new word from the letters of the word mathematics:hat
Good job, you have earned 3 points
Please construct a new word from the letters of the word mathematics:!
You have constructed:  math,cat,hat
Total score:  10 

In [21]: play_game("algorithm", dictionary)

Please construct a new word from the letters of the word algorithm:math
Good job, you have earned 4 points
Please construct a new word from the letters of the word algorithm:math
You have already found this word!
Please construct a new word from the letters of the word algorithm:algo
I do not know this word!
Please construct a new word from the letters of the word algorithm:girl
Good job, you have earned 4 points
Please construct a new word from the letters of the word algorithm:algorithm
Let's try something more interesting!
Please construct a new word from the letters of the word algorithm:tom
I do not know this word!
Please construct a new word from the letters of the word algorithm:atom
I do not know this word!
Please construct a new word from the letters of the word algorithm:log
Good job, you have earned 3 points
Please construct a new word from the letters of the word algorithm:!
You have constructed:  math,girl,log
Total score:  11
Upload form is only available when connected

Exercise 6: Writing a super-player

You may think like if I was a machine, I could just go over the whole dictionary.... Well, you do have a machine at your disposal! Write a function superplayer() taking as arguments mainword and dictionary. The function should return a list of all the words in the dictionary which could be constructed from the mainword (not counting the mainword!) and the corresponding score.

def superplayer(mainword, dictionary):
    """finds all the words which can be constructed using the letters of `mainword`.
    returns the list of these words and the total number of letters in them.
    """
    pass  # remove this line and replace with your own code

Testing

Test your function superplayer() in the console; for example, you should have the following behavior:

In [22]: dictionary = read_dictionary("dict2.txt")

In [23]: superplayer("mathematics", dictionary)
Out[23]: (['meat', 'math', 'tea', 'chest', 'hat', 'time', 'heat', 'state', 
            'test', 'site', 'case', 'cash', 'act', 'item', 'ice', 'taste', 
            'sea', 'seat', 'team', 'match', 'east', 'shame', 'cat', 'mate', 
            'she', 'set', 'teach', 'hit', 'eat', 'tie', 'hate'], 119)

In [24]: superplayer("algorithm", dictionary)
Out[24]: (['art', 'goal', 'math', 'hair', 'ratio', 'girl', 'hat', 'air', 
            'light', 'oil', 'log', 'arm', 'mail', 'harm', 'might', 'hit'], 60)

In [25]: superplayer("algorithm", [])
Out[25]: ([], 0)

In [26]: superplayer("ALGORITHM", dictionary)
Out[26]: ([], 0)

In [27]: superplayer("abracadabra", dictionary)
Out[27]: (['card', 'bad', 'car', 'bar'], 13)
Upload form is only available when connected

Exercise 7: Constructing explicitly

Our function is_constructable can define if the target word can be constructed from the letters of the source word, but even if the output is True is not always so easy to see. In this exercise, we will create a more “visual” version of this function. Write a function is_constructable2 which takes as input words target and source (both are assumed to contain only lower case letters) and does the following:

  • if target cannot be constructed from the letters of source, return None
  • otherwise, return source where letters of target are transfromed to the uppercase. For example, for target and source being cat and mathematics, one possible output is maThemAtiCs (the other a and other t could be uppercased instead).
def is_constructable2(target, source):
    """if target cannot be construtced using the letters of source, returns None.
    otherwise, returns a copy of source with the letters used 
    to construct target being in the upper case
    """
    pass  # remove this line and replace with your own code

Testing

Test your function is_constructable2() in the console; for example, you should have the following behavior:

In [28]: is_constructable2("cat", "mathematics")
Out[28]: 'mAThematiCs'

In [29]: is_constructable2("elephant", "mathematics")

In [30]: is_constructable2("card", "abracadabra")
Out[30]: 'AbRaCaDabra'

In [31]: is_constructable2("hair", "algorithm")
Out[31]: 'AlgoRItHm'
Upload form is only available when connected