Part I due by 11:59 p.m. on Thursday, February 8, 2024
Part II due by 11:59 p.m. on Sunday, February 11, 2024
In your work on this assignment, make sure to abide by the collaboration policies of the course.
If you have questions while working on this assignment, please
come to office hours, post them on Piazza, or email
cs111-staff@cs.bu.edu
.
Make sure to submit your work on Gradescope, following the procedures found at the end of Part I and Part II.
If you haven’t already created a folder named cs111
for your
work in this course, follow these
instructions to do so.
Then create a subfolder called ps2
within your cs111
folder,
and put all of the files for this assignment in that folder.
Problems 0, 1 and 2 will all be completed in a single PDF file. To create it, you should do the following:
Access the template that we have created by clicking on this link and signing into your Google account as needed.
When asked, click on the Make a copy button, which will save a copy of the template file to your Google Drive.
Select File->Rename, and change the name of the file to
ps2pr012
.
Add your work for Problems 0, 1 and 2 to this file.
Once you have completed all of these problems, choose
File->Download->PDF document, and save the PDF file in your ps2
folder. The resulting PDF file (ps2pr012.pdf
) is the one that you
will submit. See the submission guidelines at the end of Part I.
5 points; individual-only
Artificial intelligence (AI for short) is one of the many subfields of computer science. Researchers in AI focus on many different types of problems, but recently there has a great deal of focus on generative AI – the technology behind ChatGPT and other similar tools.
This week’s reading is a New York Times article about chatbots like ChatGPT. The reading is available here. If you can’t access the Times site, you can find a PDF version here.
After you have read the article, write a response that addresses the following prompt: What was the most interesting or important idea in this article for you – and why?
Important: Put your response in the copy of the ps2pr012
template that you created on Google Drive (see above).
Once again, you only need to write a short paragraph (4-6 sentences). The important thing is that your response shows you have thought critically about the article and added your own experience or insights to its ideas.
10 points; individual-only
To prepare for this problem, we encourage you to review the following video as needed:
Consider the following Python program:
def foo(a, b): c = bar(a) b = c + bar(b - 2) return b def bar(b): a = b * 2 print('bar:', a, b) return a a = 7 b = 3 print(a, b) bar(a) print(a, b) a = foo(b, a) print(a, b)
In the Problem 1 section of ps2pr012
, we have provided tables for you
to complete. We have started some of the tables for you. You should:
You may not need all of the rows provided in the tables.
10 points; individual-only
Consider the following recursive function:
def mystery(a, b): if a * b == 0: return a else: myst_rest = mystery(a - 1, b - 2) return b + myst_rest
Trace the execution of the following call to this function
mystery(3, 7)
To do so, complete the template that we have provided in
section 2-1 of ps2pr012
. In particular, you should:
Include a separate “frame” for each call. We have filled in
some of the components of the frames for the first two calls
for you. You should replace each ...
with the appropriate
integer, and you should add frames for additional calls as
needed, until you reach the base case.
Begin each frame with lines that explicitly state the values assigned to the parameters, as we have done for the first call.
Next, if the call is a base case, you can simply show the value
that is returned (omitting the line for myst_rest
). If the
call is a recursive case, you should show the recursive call
on the line for myst_rest
.
Once you have reached the base case, you should work your way
back through the frames for the previous calls. Add in both
the results of the recursive call (i.e, the value assigned to
myst_rest
) and the value returned by the call itself.
We took a similar approach to tracing recursion in Lab 3.
What is the value returned by mystery(3, 7)
?
During the execution of mystery(3, 7)
, stack frames are added
and then removed from the stack. How many stack frames are on the
stack when the base case is reached? You should assume that the
initial call to mystery(3, 7)
is made from the global scope, and
you should include the stack frame for the global scope in your
count.
Give an example of specific values of a
and b
that would produce
infinite recursion, and explain why it would occur.
You may find it helpful to use the
Python Tutor visualizer
to strengthen your intuition about how recursion works, to check your answers
to parts 1-3 of this problem, and to test and debug the functions that
you write in the later problems. For example, to test the mylen
function that we discussed in lecture, you could paste the following
into the visualizer:
def mylen(s): if s == '': return 0 else: len_rest = mylen(s[1:]) return 1 + len_rest test = mylen('cs111') print('test is', test)
18 points; individual-only
This problem involves more practice in writing non-recursive functions. These functions should be written without the use of recursion.
In Spyder, open a new editor window using File -> New File,
and save it to your ps2
folder using the name ps2pr3.py
.
Important guidelines
Include comments at the top of the file that are similar to the
ones that we gave you at the top of
ps1pr2.py
.
Your functions must have the exact names specified below,
or we won’t be able to test them. Note in particular that the
case of the letters matters (all of them should be lowercase),
and that some of the names include an underscore character (_
).
As usual, each of your functions should include a docstring that describes what your function does and what its inputs are.
Make sure that your functions return the specified value,
rather than printing it. None of these functions should use a
print
statement.
You should not use any Python features that we have not discussed in lecture or read about in the textbook.
Your functions do not need to handle bad inputs – inputs with a type or value that doesn’t correspond to the description of the inputs provided in the problem.
Leave one or two blank lines between functions to make things more readable.
Test each function after you write it. Here are two ways to do so:
Run your file after you finish a given function. Doing so will bring you to the IPython console, where you can call the function using different inputs and check to see that you obtain the correct outputs.
Add test calls to a test
function like the one that we gave
you at the bottom of the ps1pr3.py
starter file from the last problem set.
After running your ps2pr3.py
file, you can call the test
function (by entering test()
) to see the results of all of
the test calls.
To allow the Gradescope Autograder to run, you must put any test code inside a function. Do not add any lines of code that belong to the global scope of the program (i.e., lines that are outside of any function).
Write a function len_diff(s1, s2)
that takes as inputs two
string values s1
and s2
, and that returns the
the difference between their lengths as a non-negative number.
For example:
>>> len_diff('program', 'code') result: 3
Note that the function returns 7 - 4 = 3, because the length of
'program'
is 7, the length of 'code'
is 4, and thus the
difference between the lengths of the two strings is 3.
You must use conditional execution to ensure that the result is non-negative. For example, if we swap the two strings in the earlier example, we should still get the same result:
>>> len_diff('code', 'program') result: 3
Here are some other examples:
>>> len_diff('begin', 'again') result: 0 >>> len_diff('another', 'one') result: 4 >>> len_diff('one', 'another') result: 4
Warning
Make sure that your function returns the correct value
rather than printing it. If your function is printing the
return value, you won’t see an output prompt (the result:
prompt above) before the return values. If you don’t see that
prompt, you must fix your function so that it uses a return
statement rather than a print
statement. This same warning
applies to all of the functions that you will write for
this assignment, with the exception of the optional test
functions that you may include for testing your code.
Write a function combine(s1, s2, n)
that takes as inputs two
strings s1
and s2
and an integer n
, and that returns a new
string in which the first n
characters of s1
are followed
by the last n
characters of s2
. For example:
>>> combine('computer', 'science', 4) result: 'compence' >>> combine('python', 'code', 2) result: 'pyde'
If either string (s1
or s2
) does not have at least n
characters, you should use all of its characters:
>>> combine('you', 'program', 4) result: 'yougram' >>> combine('afternoon', 'fun', 5) result: 'afterfun'
Hint: We encourage you to use concrete cases to determine the logic of what the function needs to do. For example, consider the first test above:
>>> combine('computer', 'science', 4) 'compence'
In this test case, the function needs to take the strings
'computer'
and 'science'
and create the string 'compence'
.
In order to do so, it needs to extract substrings of the original
strings and concatenate them together.
s1
(which in this case is the string
'computer'
) and the input string s2
(which in this case
is the string 'science'
)? n
(which in this case is 4)? By asking questions like these for this test case and other concrete cases, you should be able to come up with the general expressions that you can use to construct the necessary substrings, and then use those substrings to construct the final return value.
Write a function reverse_last(vals, n)
that takes as inputs a
list vals
and an integer n
, and that constructs and
returns a new list in which the last n
values of
vals
are reversed and all other values from vals
remain
in their original positions. For example:
>>> reverse_last([1, 2, 3, 4, 5, 6], 3) result: [1, 2, 3, 6, 5, 4] # reversed the last 3 values >>> reverse_last([1, 2, 3, 4, 5, 6], 4) result: [1, 2, 6, 5, 4, 3] # reversed the last 4 values >>> reverse_last([10, 20, 30, 40], 2) result: [10, 20, 40, 30] # reversed the last 2 values
If n
is greater than or equal to the length of vals
, the entire
list should be reversed:
>>> reverse_last([10, 20, 30, 40], 6) result: [40, 30, 20, 10] # 6 >= 4, so reversed entire list
12 points; individual-only
In this problem you will write functions that employ the power of recursion!
In Spyder, open a new editor window using File -> New File,
and save it to your ps2
folder using the name ps2pr4.py
.
Important guidelines
The guidelines for Problem 3 also apply here.
You must use recursion in your solution to these problems.
You may not use any iterative constructs that you may be
aware of (for
, while
, etc.), and you may not use list
comprehensions.
In each case, the function that you write must call itself.
Here are the descriptions of the functions:
Write a function total_len(words)
that takes as input a list of 0
or more strings words
and uses recursion to compute and
return the value obtained by adding together the lengths of
all of the strings in the list. For example:
>>> total_len(['hi', 'there']) # 2 + 5 = 7 result: 7 >>> total_len(['recursion', 'is', 'fun']) # 9 + 2 + 3 = 14 result: 14 >>> total_len(['bye']) result: 3 >>> total_len([]) result: 0
Hints:
This function is somewhat similar to the mylen
function from
lecture, but it needs to deal with a list of strings instead
of just a single string, and it needs to add the lengths of
the strings in the list instead of just adding 1 for each
character in the string. You can find a modified version of
mylen
that handles both strings and lists here.
To figure out the logic for what you need to do after the recursive call, use concrete cases! For example:
We know that total_len(['recursion', 'is', 'fun'])
should call
total_len(['is', 'fun'])
.
What should each of these calls return, based on what this function is supposed to do?
How can we use the value returned by total_len(['is',
'fun'])
to figure out what total_len(['recursion',
'is', 'fun'])
should return?
Write a function exclaim(s)
that takes an arbitrary string s
as input and uses recursion to form and return the
string formed by adding an exclamation point (i.e., the character '!'
)
after each character in the string s
. Here are four examples:
>>> exclaim('hello') result: 'h!e!l!l!o!' >>> exclaim('wow') result: 'w!o!w!' >>> exclaim('o') result: 'o!' >>> exclaim('') result: ''
This function is somewhat similar to the remove_spaces
function from Lab 3, because it needs to
recursively create a new string from an existing string. However,
your function will be simpler, because it won’t need to decide
what to do after the recursive call returns.
Don’t forget to test your functions using the approaches mentioned at the start of Problem 3.
Login to Gradescope by clicking the link in the left-hand navigation bar, and click on the box for CS 111.
You will make submissions to two separate assignments on Gradescope. The steps needed for the two submissions are different, so please make sure to follow carefully the procedures outlined below.
PS 2: Problems 0-2
Submit your ps2pr012.pdf
file using these steps:
If you still need to create a PDF file, open your file
on Google Drive, choose File->Download->PDF document, and
save the PDF file in your ps2
folder.
Click on the name of the assignment in the list of assignments on Gradescope. You should see a pop-up window labeled Submit Assignment. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)
Choose the Submit PDF option, and then click the Select PDF button and find the PDF file that you created. Then click the Upload PDF button.
You should see a question outline along with thumbnails of the pages from your uploaded PDF. For each question in the outline:
As you do so, click on the magnifying glass icon for each page and doublecheck that the pages that you see contain the work that you want us to grade.
Once you have assigned pages to all of the problems in the question outline, click the Submit button in the lower-right corner of the window. You should see a box saying that your submission was successful.
If needed, use the Resubmit button at the bottom of the page to resubmit your work.
PS 2: Problems 3 and 4
Submit your ps2pr3.py
and ps2pr4.py
files using these steps:
Click on the name of the assignment in the list of assignments. You should see a pop-up window with a box labeled DRAG & DROP. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)
Add both files to the box labeled DRAG & DROP. You can either drag and drop the files from their folder into the box, or you can click on the box itself and browse for the files.
Click the Upload button.
You should see a box saying that your submission was successful.
Click the (x)
button to close that box.
The Autograder will perform some tests on your files. Once it is done, check the results to ensure that the tests were passed. If one or more of the tests did not pass, the name of that test will be in red, and there should be a message describing the failure. Based on those messages, make any necessary changes. Feel free to ask a staff member for help.
Note: You will not see a complete Autograder score when you submit. That is because additional tests for at least some of the problems will be run later, after the final deadline for the submission has passed. For such problems, it is important to realize that passing all of the initial tests does not necessarily mean that you will ultimately get full credit on the problem. You should always run your own tests to convince yourself that the logic of your solutions is correct.
If needed, use the Resubmit button at the bottom of the page to resubmit your work. Important: Every time that you make a submission, you should submit all of the files for that Gradescope assignment, even if some of them have not changed since your last submission.
Near the top of the page, click on the box labeled Code. Then click on the name of each file to view its contents. Check to make sure that the files contain the code that you want us to grade.
Important
It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.
If you are unable to access Gradescope and there is enough
time to do so, wait an hour or two and then try again. If you
are unable to submit and it is close to the deadline, email
your homework before the deadline to
cs111-staff@cs.bu.edu
—>
20 points; pair-optional
This is the only problem from this assignment that you may complete with a partner. See the rules for working with a partner on pair-optional problems for details about how this type of collaboration must be structured.
This problem provides more practice in writing recursive functions.
In Spyder, open a new editor window using File -> New File,
and save it to your ps2
folder using the name ps2pr5.py
.
Follow the same guidelines that we gave you for Problems 3 and 4.
Write a function add(vals1, vals2)
that takes as inputs two
lists of numbers, vals1
and vals2
, and that uses
recursion to construct and return a new list in which
each element is the sum of the elements at the corresponding positions
in the original lists. For example:
>>> add([1, 2, 3], [4, 5, 6]) result: [5, 7, 9]
Note that the elements in the result are obtained by adding the
corresponding elements from the original lists (1+4
, 2+5
, and
3+6
).
Here are some other examples:
>>> add([5, 3], [6, 4]) result: [11, 7] >>> add([1, 2, 3, 4], [20, 30, 50, 80]) result: [21, 32, 53, 84] >>> add([5, 3], [6]) # lists with different lengths result: []
Hints:
Base cases: If the two lists do not have the same length
or if either list is empty, the function should return an empty list
([]
).
Although you could combine these cases into one if
statement,
we recommend that you check for them separately.
Here is some pseudocode (i.e., a mixture of Python code and descriptive text) for this function:
def add(vals1, vals2): """ docstring goes here """ if the lists don't have the same length: return [] elif either list is empty: return [] else: add_rest = add(_____, ______) return ________________
You should turn this pseudocode into Python code. In particular, you will need to replace the blanks that we have included with the appropriate expressions.
To figure out the logic for what you need to do after the recursive call, use concrete cases! For a reminder of how to do so, see the third suggestion in our answer for question 7 in the section on General Questions in the FAQ.
Important: In the recursive case, when you use concatenation
to build a larger list, make sure that both of the operands are lists.
For example, if x
is an integer and vals
is a list, the
following will produce an error:
x + vals # error: cannot add an integer to a list
Instead, you would need to turn x
into a list before adding it:
[x] + vals # correct!
See the FAQ for more help with this problem.
Write a function contains(s, c)
that takes an arbitrary string
s
and a single-character c
as inputs and uses recursion
to determine if s
contains the character c
, returning
True
if it does and False
if it does not.
To force you to use recursion, you may not use the in
operator. Rather, you should use recursion to process s
one
character at a time and determine if c
is contained in s
.
For example:
>>> contains('hello', 'e') result: True >>> contains('hello', 'l') result: True >>> contains('hello', 'x') result: False >>> contains('', 'x') result: False
Warning
Your function should return a boolean value – either True
or False
, without any quotes around them. If you see
quotes around the result when you make the calls above
from the console, you must fix your function to remove the
quotes.
Hints:
You will need two base cases:
one base case for the smallest possible input for the
parameter s
one base case for when the first character in the string is the one you are looking for; this case is a base case because you don’t need to reduce the problem any further in order to know what value to return.
You must check for these base cases in the order given above. Otherwise, you can end up with an error!
Here is some pseudocode (i.e., a mixture of Python code and descriptive text) for the function:
def contains(s, c): """ docstring goes here """ if s is the empty string: return the appropriate boolean value elif the first character of s is a match for c: return the appropriate boolean value else: contains_rest = contains(_____, c) return ____________
You should turn this pseudocode into Python code. In particular, you will need to replace the blanks that we have included with the appropriate expressions.
See the FAQ for more help with this problem.
Write a function process(vals)
that takes as input a list of 0
or more integers vals
and uses recursion to create and
return a new list in which each even element of the original
list has been tripled and each odd element has been left
unchanged. For example:
>>> process([5, 4, 3, 2]) result: [5, 12, 3, 6]
Note that the two even numbers from the original list (4
and
2
), have been replaced with their tripled values (12
and
6
). The other two numbers (5
and 3
) have been left unchanged
because they are odd.
Here are some other examples:
>>> process([6, 3, 10]) result: [18, 3, 30] :::python >>> process([]) result: []
Hints:
This function is somewhat similar to the replace
function from lecture. That function recursively
creates a new string from an existing string, whereas this
function will recursively create a new list from an existing
list.
Don’t forget that you can use the modulus operator (%
) to test
if an integer is odd or even.
Here again, when you use concatenation to build a larger list,
make sure that both sides of the +
operator are
lists. See the note that accompanies the add
function
above for more detail.
Don’t forget to test your functions using the approaches mentioned at the start of Problem 3.
25 points; individual-only
This problem provides more practice in writing functions, including three recursive functions.
In Spyder, open a new editor window using File -> New File,
and save it to your ps2
folder using the name ps2pr6.py
.
Follow the same guidelines that we gave you for Problems 3 and 4. For parts 2, 3 and 4, you must use recursion.
Write a function letter_score(letter)
that takes a lowercase
letter as input and returns the value of that letter as a
scrabble tile. If letter
is not a lowercase letter from ‘a’ to ‘z’,
the function should return 0. This function does not require
recursion.
Here is the mapping of letters to scores that you should use:
For example:
>>> letter_score('w') result: 4 >>> letter_score('q') result: 10 >>> letter_score('%') # not a letter result: 0 >>> letter_score('A') # not lower-case result: 0
We encourage you to begin with the following template:
def letter_score(letter): """ your docstring goes here """ assert(len(letter) == 1) # put the rest of your function here
Note that we begin with an assert
statement that validates the
input for the parameter letter
. If the condition given to assert
is
not true–in this case, if the input provided for letter
has a
length other than 1–then assert
will cause your code to crash
with an AssertionError
. Using assert
in this way can help you
to find and debug situations in which you accidentally pass in
incorrect values for the parameter of a function.
Hints:
You will need to use conditional execution (if-elif-else
) to
determine the correct score for a given letter.
You can greatly reduce the number of cases if you use the in
operator. For example:
if letter in ['b', 'c', 'm', 'p']: # letters with a score of 3 return 3 elif letter in ...
Write a function scrabble_score(word)
that takes as input a
string word
containing only lowercase letters, and that uses
recursion to compute and return the scrabble score of
that string – i.e., the sum of the scrabble scores of its
letters. For example:
>>> scrabble_score('python') result: 14 >>> scrabble_score('a') result: 1 >>> scrabble_score('quetzal') result: 25
In addition to calling itself recursively, the function must
also call your letter_score
function to determine the score of a
given letter. Doing so will allow you to avoid repeating the
long if-elif-else
statement that is already present in
letter_score
. Indeed, the only if-else
statement that you
should need is the one that determines whether you have a base
case or recursive case.
See the FAQ for more help with this problem.
Write a function smaller_of(vals1, vals2)
that takes as inputs
two lists vals1
and vals2
and uses recursion to
construct and return a new list in which each element is the
the smaller of the corresponding elements from the original
lists. If the two elements for a given position have the same value,
you should include that value. For example:
>>> smaller_of([3, 4, 9, 5], [7, 2, 0, 5]) result: [3, 2, 0, 5]
In the return value for this case:
The first element is 3, because 3 is the smaller of the first elements of the original lists (3 and 7).
The second element is 2, because 2 is the smaller of the second elements of the original lists (4 and 2).
The third element is 0, because 0 is the smaller of the third elements of the original lists (9 and 0).
The fourth element is 5, because 5 is the value of both of the fourth elements of the original lists.
Here are two other examples:
>>> smaller_of([5, 7, 2], [1, 9, 15]) result: [1, 7, 2] >>> smaller_of([], []) result: []
If one of the lists is longer than the other, its “extra” elements should be ignored. For example:
>>> smaller_of([0, 3, 6, 9], [1, 1]) # two extra elements in first list result: [0, 1] >>> smaller_of([3, 1, 0], [2, 4, 5, 6]) # one extra element in second list result: [2, 1, 0]) >>> smaller_of([1, 2], []) # all of the first list's values are extra! result: [] >>> smaller_of([], [3, 4, 5]) # all of the second list's values are extra! result: []
Write a function merge(s1, s2)
that takes as inputs two strings
s1
and s2
and uses recursion to determine and
return a new string that is formed by “merging” together the
characters in the strings s1
and s2
to create a single string.
If s1
and s2
have the same character at a given position,
it should be included once in the returned string.
If s1
and s2
have different characters at a given position,
both characters should be included in the returned string:
first the character from s1
, then the character from s2
.
For example:
>>> merge('abcde', 'abghe') result: 'abcgdhe'
In this case:
The first character of both strings is 'a'
, so it is
included once in the return value.
The second character of both strings is 'b'
, so it is
included once in the return value.
The third characters of the two strings are different
('c'
and 'g'
), so the return value includes 'c'
followed
by 'g'
.
The fourth characters of the two strings are different
('d'
and 'h'
), so the return value includes 'd'
followed
by 'h'
.
The fifth character of both strings is 'e'
, so it is
included once in the return value.
Here are some other examples:
>>> merge('string', 'sprung') result: 'stpriung' >>> merge('same', 'same') # no differences! result: 'same' >>> merge('abc', 'efg') # all different! result: 'aebfcg' >>> merge('', '') result: ''
If one of the strings is longer than the other, its “extra” characters – the ones with no counterparts in the shorter string – should appear immediately after the “merged” characters (if any) in the returned string.
>>> merge('loudest', 'song') # 'est' is extra result: 'lsoundgest' >>> merge('abc', 'aaadd') # 'dd' is extra result: 'abacadd' >>> merge('abc', '') # 'abc' is extra result: 'abc' >>> merge('', 'de') # 'de' is extra result: 'de'
Hint: You will need more than one base case.
Don’t forget to test your functions using the approaches mentioned at the start of Problem 3.
Login to Gradescope by clicking the link in the left-hand navigation bar, and click on the box for CS 111.
Submit your ps2pr5.py
and ps2pr6.py
files using these steps:
Click on the name of the assignment in the list of assignments. You should see a pop-up window with a box labeled DRAG & DROP. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)
Add both files to the box labeled DRAG & DROP. You can either drag and drop the files from their folder into the box, or you can click on the box itself and browse for the files.
Click the Upload button.
You should see a box saying that your submission was successful.
Click the (x)
button to close that box.
The Autograder will perform some tests on your files. Once it is done, check the results to ensure that the tests were passed. If one or more of the tests did not pass, the name of that test will be in red, and there should be a message describing the failure. Based on those messages, make any necessary changes. Feel free to ask a staff member for help.
Note: You will not see a complete Autograder score when you submit. That is because additional tests for at least some of the problems will be run later, after the final deadline for the submission has passed. For such problems, it is important to realize that passing all of the initial tests does not necessarily mean that you will ultimately get full credit on the problem. You should always run your own tests to convince yourself that the logic of your solutions is correct.
If needed, use the Resubmit button at the bottom of the page to resubmit your work. Important: Every time that you make a submission, you should submit all of the files for that Gradescope assignment, even if some of them have not changed since your last submission.
Near the top of the page, click on the box labeled Code. Then click on the name of each file to view its contents. Check to make sure that the files contain the code that you want us to grade.
Important
It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.
If you are unable to access Gradescope and there is enough
time to do so, wait an hour or two and then try again. If you
are unable to submit and it is close to the deadline, email
your homework before the deadline to
cs111-staff@cs.bu.edu
Last updated on February 8, 2024.