Because this is also the week of the midterm, this lab is due at noon on Friday for everyone.
In this lab, we will focus on debugging, the process of finding and fixing mistakes in our code. The goal of this lab is to gain experience with the following:
When programming, you may encounter three main types of errors:
Syntax errors. These are textual errors that are identified by Python before it attempts to run the program. For example, if you forget a colon after the function definition, e.g.,
def add(x, y) # forgot the colon here
return x + y
or forget to indent properly, e.g.,
def add(x, y):
return x + y # function body should be indented
Python will complain that your syntax is incorrect. These errors, while annoying, are typically the easiest to correct.
Runtime errors. When the program begins
running, there are some conditions that may unexpectedly arise that
Python will complain about. For example, suppose you compute the current
of a circuit using the following function definition, found in a file
physics.py
:
def current(total_voltage, total_resistance):
return total_voltage / total_resistance
It is possible that total_resistance
is 0
.
If so, the computation attempts to illegally divide by zero:
Traceback (most recent call last):
File "physics.py", line 29, in current
return total_voltage / total_resistance
ZeroDivisionError: division by zero
Logic errors. Sometimes when we
translate an algorithm into code we may introduce mistakes in logic. For
example, we may reset a variable to zero, or append a value incorrectly
within a conditional, etc. Logic errors are among the hardest bugs to
isolate and debug, because even though your program runs just fine, it
fails to do what you expect it to do. For example, the following
function to count the number of times a value appears in a sequence
does return a valid integer, but that integer’s value is
incorect—count
will always be 0
, even if
value
appears in the sequence
.
def count_occurrences(value, sequence):
= 0
count for element in sequence:
if element == value:
+ 1 # we aren't saving our updated count
count return count
As we investigate our scripts this week, we will want to carefully read the hints that Python gives us. For example, when syntax error messages are printed, they include line numbers. The error is very likely at or before the indicated line number. Fortunately, all modern text editors (like VS Code) show us line numbers for our written code.
When a runtime error occurs, the Python system often prints a stack trace or traceback. This is a list of lines in the program that are currently being executed. Information about the most recent line appears near the bottom of the trace. Carefully reading the stack trace can give you important clues about what your program was doing when it stopped running.
Logic errors often stem
from incorrect assumptions about the state of the program. To fix them,
it is often helpful to get a better view of the program’s variables so
that we can verify the accuracy of the assumptions we make. The
judicious use of print(...)
statements can help to isolate
sections of the code that lead to unexpected values in state.
To get started on this week’s lab, you should clone the
lab05
repository in the usual manner:
git clone https://evolene.cs.williams.edu/cs134-labs/23xyz3/lab05.git
Remember to replace 23xyz3
with your CS username.
Everything that you need to complete this week’s assignment is found in
this repository.
To complete this lab, you must find and fix errors in two of the scripts we’ve included in this week’s repository.
The script swedishpuzzle.py
is filled with syntax
errors. This script is inspired by a Swedish word puzzle game called
“Rövarspråket”. Given a string word
and letter
letter
, the rules of “Rövarspråket” ask for a new word
which is created as follows:
word
is doubled and the supplied
letter
is inserted between (e.g. 'n'
becomes
'non'
when 'o'
is supplied; 'xz'
becomes 'xoxzoz'
when 'o'
is supplied).word
remain untouched.Ideally, the function convert
in
swedishpuzzles.py
takes a letter and a word as input (both
of type str
) and returns a new string answer
according to the rules of the game. The logic of the included script is
sound, but there are many syntax errors that you must fix. As you fix
errors, mark each corrected line with the comment “#FIXED,” so we know
what you changed. As you get started, you should consider adding some
print statements to see how the state of variables are changing on each
execution of the loop.
Once you have fixed all the errors, then running the script
python3 swedishpuzzle.py
should print the following:
Let's call convert on u and
it returns
Let's call convert on o and stubborn
it returns sostotubobboborornon
Let's call convert on o and pp
it returns poppop
Note that your output should match the output shown above. If necessary, you should comment out (or remove) any additional print statements that you used while debugging.
The script vowelacious.py
contains two buggy versions of
the function is_vowelacious
. We call a word
vowelacious if it contains three or more consecutive
vowels. For example, the word 'vowelacious'
is
itself vowelacious because of the substring iou
. A correct
is_vowelacious
function should take a word
(string) as input, and return True
if it is vowelacious;
else it should return False
.
We have given you two incorrect implementations of this function:
is_vowelacious_failed_attempt1
and
is_vowelacious_failed_attempt2
. You must analyze each of
these functions to identify the logic errors. You may add as many print
statements as you try to figure out where the code might be going wrong,
but please do not modify the logic of these functions
and remove the extra print statements before you turn in your code.
In addition to finding the logic errors, you must also complete the following three subtasks:
At the top of the file, there are 3 variables:
attempt_1_vowelacious
,
attempt_1_not_vowelacious
, and
attempt_1_buggy
. Set these strings to be words satisfying
the following criteria.
attempt_1_vowelacious
is a Vowelacious
word and
is_vowelacious_failed_attempt1(attempt_1_vowelacious)
returns True
.attempt_1_not_vowelacious
is a
non-Vowelacious word and
is_vowelacious_failed_attempt1(attempt_1_not_vowelacious)
returns False
.attempt_1_buggy
is a Vowelacious word
but is_vowelacious_failed_attempt1(attempt_1_buggy)
returns
False
.In other words, find two inputs for which the function works properly, and then an input for which the function produces a “false negative”.
Similarly, set attempt_2_vowelacious
,
attempt_2_not_vowelacious
, and attempt_2_buggy
to strings satisfying the same criteria for the second broken version of
our function, is_vowelacious_failed_attempt_2
:
attempt_2_vowelacious
is a Vowelacious
word and is_vowelacious_failed_attempt_2(buggy2Vowelacious)
returns True
.attempt_2_not_vowelacious
is a
non-Vowelacious word and
is_vowelacious_failed_attempt_2(buggy2NotVowelacious)
returns False
.attempt_2_buggy
is a Vowelacious word
but is_vowelacious_failed_attempt_2(buggy1Bad)
returns
False
.Fill in the TODO comment in the docstring for both buggy functions to briefly describe the logic error.
Finally, complete the is_vowelacious
function with
the correct implementation.
You can put function calls to test your functions directly in the
if __name__ == "__main__":
block at the end of the file.
This code will only run when the python file is run as a script.
As you finish identifying and removing bugs in each script, do not forget to add, commit, and push your work to the server.
Update your README.md
to record
collaborations.
As always, the file GradeSheet.txt
in your
lab05
repository goes over the grading guidelines and
documents our expectations.