homework1PRINT

advertisement
EECS110 Homework 1, Spring 2009
Due: 11:59pm on Sunday April 12, 2009
Submission: submit your solutions at the submissions server
If you are working on lab problems, please go to:
http://cs.northwestern.edu/~akuzma/classes/EECS110-s09/lab/lab1/lab1.htm
You should do the first two problems for Lab1.
Problems:
Problem 1: Data (hw1pr1.py) [25 points; individual or pair]
Week 1, Problem 1: Data!
[25 points; individual or pair]
Part 0: Logging in and running Python and IDLE
An easy way to start Python and IDLE is by clicking on the IDLE icon in the
"dock" at the bottom of the screen. It's the one with the stylized yellow and
blue pythons on it. If you can’t find it, click the Windows start button shown
below:
and click on IDLE for Python. After that, open a new file and add a suitable
comment at the top—for example:
# Homework 1, Problem 1 (Lab)
# 04/07/09
Save your file as hw1pr1.py - perhaps on the desktop (easy to find) or in a
new folder (better organized).
Page 2 of 26
Part 1: working at the Python interpreter (or shell)
Arithmetic with numbers, lists, strings, and booleans.
To get started, try a few arithmetic, string, and list expressions in the Python
interpreter, e.g.,
>>> 40 + 2
42
>>> 40 ** 2
1600
>>> 40 % 2
0
>>> 'hi there!'
hi there! (notice Python's politeness!)
>>> 'who are you?'
who are you? (though sometimes it's a bit touchy.)
>>> L = [0,1,2,3] You can label data (here, a list) with a name (here,
the name L)
(no response from Python)
>>> L
[0,1,2,3] You can see the data (here, a list) referred to by a name (here,
L)
>>> L[1:]
[1,2,3] You can slice lists (here, using the name L)
>>> L[::-1]
[3,2,1,0] You can reverse lists (or strings!) using "skip"-slicing with a -1
as the amount to skip.
>>> [0,1,2,3][1:]
[1,2,3] You can slice lists using the raw list instead of the name (Not that
Page 3 of 26
this would be very useful, admittedly!)
>>> 100*L + [42]*100
(a list with 500 elements that I'm too lazy to type here)
>>> L = 42 You can reassign the name L to another value, even of a
different type- now, L names the integer 42, instead of the list it used to
represent.
(no response from Python)
>>> L == 42 Two equals are different than 1! This tests for equality.
True
>>> L != 42 This tests for "not equal."
False
Errors or Exceptions
If you didn't type things in perfectly, Python will reply with an error or an
exception, as it is often called. See if you can make Python create the
following exceptions, but don't spend more than a minute or so in total!
SyntaxError
TypeError (try slicing an integer for example!)
ZeroDivisionError
IndexError (try an out-of-bounds index)
OverflowError (remember that integers will crash the machine before
overflowing)
Part 2: Lists of integers
This problem will exercise your slicing-and-indexing skills. First, you should
copy (or type) into your hw1pr1.py file the following lines:
# starting lists for part 2
pi = [3,1,4,1,5,9]
e = [2,7,1]
Page 4 of 26
When you hit F5 (or click Run and then click Run Module F5), these two lists
will be recognized by the Python shell.
The challenge is to create several lists using only the list labeled pi, the list
labeled e, and the four list operations here -list indexing pi[0]
list slicing e[1:]
list concatenation, + pi[:1] + e[1:]
(don't use + to add values
numerically)
the list-making operator, [ , ] [ e[2], e[0] ]
For each one, place your answer into an appropriate variable in your
hw1pr1.py file (see example below). Include a comment on the line above,
as well. Though not mandatory, you might try to use as few operations as
possible, to keep your answers elegant and efficient. For example,
Example problem Use pi and/or e to create the list [2,5,9]. Store this list
in the variable answer0.
Answer to the example problem
# Creating the list [2,5,9]
answer0 = [e[0]] + pi[-2:]
Please leave a blank line or two between your answers (to keep the graders
happy)!
Remember that you can use the python interpreter to try things out!
Here are the problems:
Use pi and/or e to create the list [7,1]. Store this list in the variable
answer1.
Use pi and/or e to create the list [9,1,1]. Store this list in the variable
answer2.
Page 5 of 26
Use pi and/or e to create the list [1,4,1,5,9]. Store this list in the variable
answer3.
Use pi and/or e to create the list [1,2,3,4,5]. Store this list in the variable
answer4.
Part 3: Strings
This problem continues in the style of the last one, but uses strings
rather than lists. So, it asks you to create specified strings that result
from using only the following three string literals, which you should type
into your hw1pr1.py file at this point:
n = 'northwestern'
u = 'university'
c = 'class_eecs_110_python'
You may use any combination of these four string operations:
String indexing, e.g., n[0]
String slicing, e.g., u[1:]
String concatenation, +, e.g., c + n
Repetition, *, e.g., 42*c (using integers is OK here)
Again, less is more: the number of operations in our shortest answers
are in parentheses- you might find even more efficient ones! However,
any answer is OK - there's no requirement to use fewer operations.
Example problem: Use n and c to create 'nano'. Store this string in
the variable answer42.
Answer to example
# Creating the string 'nano'
answer42 = n[0] + c[2] + n[0] + c[-2]
Page 6 of 26
Create northeasternuniversity Store this string in the variable
answer5.
Create west_east_university Store this string in the variable
answer6.
Create nirvana Store this string in the variable answer7.
Create easterparty_110110 Store this string in the variable answer8.
Create python_110_eecs_class Store this string in the variable
answer9.
If you have gotten to this point, you have completed the first problem
from Lab 1! You should submit your hw1pr1.py file at the Submission
Site.
Problem 2: Functioning smoothly (hw1pr2.py) [25 points; individual or pair]
Week 1, Problem 2: Functioning smoothly!
[25 points; individual or pair]
Part 0: Create a new file
To hold your answers and work from this portion of the lab, use IDLE to create
a new file (or save the current one with the new name). Be sure to name the
file for this part of the lab (and homework) hw1pr2.py.
Part 1: Using built-in functions
To begin, simply use the interactive Python window to try out some of the
built-in functions:
>>> range(0,100)
[0,1,2,...,99] range returns a list of integers
>>> sum(range(0,101))
Page 7 of 26
5050 sum sums a list of numbers, and range creates a list of integers. Note that
when you use range, as with almost everything in python, the right endpoint is
omitted!
>>> sum([40,2])
42 a roundabout way of adding 40+2
>>> help(sum)
(an explanation of sum) help is a good thing—ask for it by name!
>>> dir(__builtins__)
(a huge list of built-in functions, all possible errors,
etc.)
dir is also useful, listing everything from a particular file (or
module); the special __builtins__ module is, well, built-in!
How to type__builtins__? There are two underscores both before and
after the lowercase letters: the underscore, _, is shift-hyphen on most
computer keyboards (between the right parenthesis and the plus sign).
If you look carefully in the big list of stuff returned from dir, you will find the
sum function you used above. You will not, however, find some other
important functions, for example, sin or cos or sqrt. All of these functions
(and many more) are in the math module. By the same token, there are
many, many more modules (files) of functions available for you to use….
Part 2: importing other code (or "modules")
To access functions that are not built-in by default, you need to load them from their
modules. There are a couple of ways to do this:
(1) You can import the module and then access its functions with the module name:
>>> import math
(no response from Python)
>>> math.sqrt(9)
3.0 Note that sqrt returns a float even if its input is an int.
Page 8 of 26
>>> math.cos(3.14159)
-0.999... Note that cos et al. take radians as input and 3.14159 !=
math.pi, that is to say it's only an approximation. Try math.cos(math.pi), as
well.
(2) Tired of typing math. in front of things? You can avoid this with
>>> from math import *
(no response from Python) The asterisk * here means "everything." This
will bring all of the functions and constants from the math module into your current
python environment, and you can use them without prefacing them by math.
>>> cos(pi)
-1.0
This would have had to be math.cos(math.pi) before the new "from math
import *" import statement.
Part 3. Creating your own functions in a file
Python has lots of functions, the building blocks of computation. What distinguishes
Python from other computing environments is the ease and power of creating your
own functions.
Here, we will create a few in your hw1pr2.py file. In that file, below any
comments you may have at the very top, type (or paste!) the following
function definition:
def dbl(x):
""" dbl returns twice its input
input x: a number (int or float)
"""
return 2*x
Next, load this dbl function into the interpreter by hitting the F5 key.
Then, try it out at the interpreter:
>>> dbl(21)
42
Page 9 of 26
The above code creates a function named dbl that outputs twice what it gets
as input. The string inside triple quotes """ is called the docstring
(documentation string)—this should describe what the function outputs (here
in the first line) and what the function inputs (here in the second line). It
becomes part of Python's built-in help system. Finally, in the function's last
line its work is done and the result is returned.
We will ask you to include a docstring in all of your functions (even simple
ones such as these, in order to feed the habit). This self-documenting feature
in Python is especially important for making your functions understandable,
both to others and to yourself!
Using help to access docstrings
It's worth noting that Python's help command simply prints a function's docstring. As
a result, when imported, your dbl function is already a fully-integrated part of the
Python language and help system. Try typing help(dbl) at the interpreter prompt:
>>> help(dbl)
Help on function dbl in module __main__:
dbl(x)
dbl returns twice its input
input x: a number (int or float)
Part 4: Try it out! 6 functions to write…
To begin, you may want to include the line
from math import *
or the line
import math
near the top of your hw1pr2.py file. That way, you'll be able to use any
functions from the math module as needed in your solutions.
Include a docstring that describes what your function does and what its
inputs are for each function.
Page 10 of 26
Example: Write the function tpl(x), which takes in a numeric input and
outputs three times that input.
Answer to example: might be something like this, in hw1pr2.py:
def tpl(x):
""" tpl returns thrice its input
input x: a number (int or float)
"""
return 3*x
The functions to write:
1. Write sq(x), which takes in a (floating-point) number named x as input.
Then, sq should output the square of its input.
2. interp(low,hi,fraction) takes in three numbers, low, hi, and
fraction, and should return a floating-point value that linearly interpolates
between low and hi as far as fraction specifies. That is, if fraction is
zero, low will be returned. If fraction is one, hi will be returned, and
values of fraction between 0 and 1 lead to results between low and hi.
See the examples below for additional detail.
Your function should also work if fraction is less than zero or greater than
one. In this case, it will be linearly extrapolating, rather than interpolating. But
we'll stick with the name interp anyway.
From the above description, it might be tempting to divide this function into
several cases and use if, elif, and the like. However, it is possible to write
this function without using any conditional (if) constructions at all. Some
examples:
>>> interp(1.0, 3.0, 0.25) # a quarter of the way from 1.0
to 3.0
1.5
Page 11 of 26
>>> interp(0, 10, 0.42) # 42% of the way from 0 to 10
4.2
Actually, you might get 4.2000000000000002 or something similar,
depending on your implementation. This is OK, it simply reflects the
finite precision (in binary) available to the computer.
>>> interp(24, 42, 0)
24.0
# 0% of the way from 24 to 42
>>> interp(102, 117, -4.0) # -400% of the way from 102 to
117
42.0
3. Write a function checkends(s), which takes in a string s and returns True
if the first character in s is the same as the last character in s. It returns
False otherwise. The checkends function does not have to work on the
empty string (the string '').
Examples:
>>> checkends('no match')
False
>>> checkends('hah! a match')
True
>>> help(checkends)
This function sees if the first and last characters of
its input are the same.
Input: a string, s
Of course, your docstring may be different—or, feel free to just paste this
one….
Page 12 of 26
4. Write a function flipside(s), which takes in a string s and returns a
string whose first half is s's second half and whose second half is s's first
half. If len(s) (the length of s) is odd, the first half of the input string should
have one fewer character than the second half. (Accordingly, the second half
of the output string will be one shorter than the first half in these cases.)
Here you may want to use the built-in function len(s), which returns the
length of the input string, s.
Examples:
>>> flipside('homework')
workhome
>>> flipside('carpets')
petscar
These last two functions combine string and arithmetic processing.
5. Write convertFromSeconds(s), which takes in a nonnegative integer
number of seconds s and returns a list in the same format as above. In this
case, you should be sure that
0 ≤ seconds < 60
0 ≤ minutes < 60
0 ≤ hours < 24
There are no limits on the number of days.
For instance,
>>> convertFromSeconds(610)
[0, 0, 10, 10]
>>> convertFromSeconds(100000)
Page 13 of 26
[1, 3, 46, 40]
6. Finally, write readSeconds(s), a function that takes in a number of
seconds, s, and returns a string that expresses that span of time in terms of
days, hours, minutes, and seconds - with the same constraints as in problem
9, above. Your function should handle plurals and singulars correctly, as well
(see examples).
Keep in mind that readSeconds should return a string, it should not use the
print command at all! Also, you'll likely want to call convertFromSeconds
as you write readSeconds. Here are a few examples:
>>> readSeconds(80)
0 days, 0 hours, 1 minute, 20 seconds
>>> readseconds(100000)
1 day, 3 hours, 46 minutes, 40 seconds
Submitting your file
You should submit your hw1pr2.py file at the Submission Site.
This is the end of Lab1.
Below is the rest of Homework 1.
Problem 3: Rock-paper-scissors (part 2) (hw1pr3.py) [20 points; individual]
Week 1, Problem 3: The Road Not Taken: Choosing
Code Paths
[20 points; individual]
Page 14 of 26
This problem asks you to write three Python functions that test the
use of the if elif and else constructs in python. Be sure to test
your functions carefully. Also, be sure to include a docstring under
the signature line of each function. The docstring should indicate
what the function computes (outputs) and what its inputs are or
what they mean.
Please put all of your functions for this problem in a single file
named hw1pr3.py. Thus, all of the parts of this problem will be
submitted in a single file. Please name your functions exactly as
specified (including upper/lower case) -- it will help keep the
graders happy -- which is always a good thing!
(#1) Building from last week's rock-paper-scissors game (which did
not have to be fair), for this week, write a function rps() that plays
a game of rock-paper-scissors fairly.
That is, it should first choose randomly from the three choices,
though it should not reveal that choice! Then, the function should
ask the user for her choice. Afterwards, it should print its original
choice, the user's choice, and then declare the winner.
In addition, your rps function should print a warning if the user
does not input one of 'rock', 'paper', or 'scissors'.
Choosing items at random from a sequence
To generate a random element from a list, model your code from
the following example:
from random import *
s = choice( [ 'thread', 'yarn', 'twine' ])
print 'I chose', s
Page 15 of 26
The above code will print a potentially different string each time it is
run.
Print vs. return
Note that rps() takes no inputs and it has no return value -- it's a
function that interacts with the user only via print and raw_input
statements. Thus, rps does not need to return anything. It is a
good example of a function in which print is the desired means of
interaction.
Playing again with while
Optionally, your function could use a while loop, in which it asks
the user to play again and then continue (or not), based on their
answer. This is not required, but if you'd like to do so, the following
example shows how a while loop works:
answer = 'no'
while answer == 'no':
[body of the program]
answer = raw_input('Would you like to stop? ')
Examples
Here are two separate example runs with the user's input in blue -feel free to adjust the dialog for the sake of yourself (or the
graders):
>>> rps( )
Page 16 of 26
Welcome to RPS! I have made my choice.
Choose your poison: scissors
You chose scissors.
I chose rock.
I win!
And I didn't even cheat this time!
>>> rps( )
Welcome to RPS! I have made my choice.
Choose your poison: paper
You chose paper.
I chose rock.
You win!
I may have to reconsider my strategy in this game...
Submitting your file
You should submit your hw1pr3.py file at the Submission Site.
Problem 4: Function Frenzy (hw1pr4.py) [30 points; individual or pair]
Week 1, Problem 4: Fun with Functions
[30 points; individual or pair]
This problem asks you to write the following Python functions using
recursion. Be sure to test these functions carefully. Be sure to
include a docstring under the signature line of each function. The
docstring should indicate what the function computes (outputs) and
what its inputs are or what they mean.
Page 17 of 26
Please put all of your functions for this problem in a single
hw1pr4.py file. Thus, all of the parts of this problem will be
submitted in a single file. Be sure to name your functions exactly as
specified.
Also, the mult, dot, ind, and scrabbleScore functions should all be
done using recursion. Compare them to the power, mysum, mylen,
and sajak functions we did in class this week.
1. mult( n, m ) should output the product of the two integers n
and m. Since this would be a bit too easy if the multiplication
operator * were used, for this function, you are limited to
using addition/subtraction/negation operators, along with
recursion. (Use the power function we did in class as a guide.)
Some examples:
>>> mult( 6, 7 )
42
>>> mult( 6, -3 )
-18
2. dot( L, K ) should output the dot product of the lists L and
K. If these two input lists are not of equal length, dot should
output 0.0. If these two lists are both empty, dot also should
output 0.0. You should assume that the input lists contain
only numeric values. (Compare this with the mysum example
we did in class, but be sure to use both lists...!) Recall that
the dot product of two vectors or lists is the sum of the
products of the elements in the same position in the two
Page 18 of 26
vectors. for example, the first result is 5*6 plus 3*4, which is
42.0 (if we use a float).
>>> dot( [5,3], [6,4] )
42.0
>>> dot( [1,2,3,4], [10,100,1000,10000] )
43210.0
>>> dot( [5,3], [6] )
0.0
3. Write ind(e, L), which takes in a sequence L and an element
e. L might be a string or, more generally, a list. Your function
ind should return the index at which e is first found in L.
Counting begins at 0, as is usual with lists. If e is NOT an
element of L, then ind(e, L) should return any integer larger
than or equal to len(L). It can be len(L) exactly, as shown
below in these examples:
>>> ind(42, [ 55, 77, 42, 12, 42, 100 ])
2
>>> ind(42, range(0,100))
42
>>> ind('hi', [ 'hello', 42, True ])
3
>>> ind('hi', [ 'well', 'hi', 'there' ])
1
>>> ind('i', 'team')
4
>>> ind(' ', 'outer exploration')
Page 19 of 26
5
4. letterScore( let ) should take as input a single-character
string and produce as output the value of that character as a
scrabble tile. If the input is not one of the letters from 'a' to
'z', the function should return 0.
To write this function you will need to use this mapping of
letters to scores
What!? Do I have to write 25 or 26 if elif or else statements? No!
Instead, use the in keyword:
>>> 'a' in 'this is a string including a'
True
>>> 'q' in 'this string does not have the the letter
before r'
False
Phew!
This problem does not require recursion. But it's used in the next
one... .
5. scrabbleScore( S ) should take as input a string S, which
will have only lowercase letters, and should return as output
the scrabble score of that string. Ignore the fact that, in
reality, the availability of each letter tile is limited. Hint: use
the above letterScore function and recursion. (Compare this
with the the mylen example we did in class.)
Page 20 of 26
Here are some examples:
>>> scrabbleScore('quetzal')
25
>>> scrabbleScore('jonquil')
23
>>> scrabbleScore('syzygy')
25
Submitting your file
You should submit your hw1pr4.py file at the Submission Site.
Extra Problems:
Extra Credit Option 1: Pig Latin (hw1ec1.py) [15 points, individual or pair]
Week 1, Extra Problem 1: Pig Latin
[15 points; individual or pair]
This problem is inspired by
Warm Up
[5 points]
Page 21 of 26
Write pigLatin( s ), which will take as input a string s. s will be a
single word consisting of lowercase letters. Then, pigLatin should
output the translation of s to pig latin, according to these slightly
altered rules:
If the input word has no letters at all (the empty string), your
function should return the empty string
If the input word begins with a vowel, the pig latin output simply
appends the string 'way' at the end. 'y' will be considered a
consonant, and not a vowel, for this problem.
Hint: Consonant letters in the English alphabet are B, C, D, F, G, H,
J, K, L, M, N, P, Q, R, S, T, V, W, X, Z, and Y.
Example
pigLatin('one') returns 'oneway'
If the input word begins with a consonant, the pig latin output is
identical to the input, except that the input's initial consonant is at
the end of the word instead of the beginning and it's followed by the
string 'ay'.
Example
pigLatin('be') returns 'ebay'
Of course, this does not handle words beginning with multiple
consonants correctly. For example, pigLatin('string') returns
'tringsay'.++
Don't worry about this. However, if you would like to tackle this
more challenging problem, see the extra credit, below... .
Page 22 of 26
The real pig latin challenge
[10 points]
Create a function called spamLatin( s ) that handles more than
one initial consonant correctly in the translation to Pig Latin. That is,
spamLatin moves all of the initial consonants to the end of the word
before adding 'ay'. (You may want to write and use a helper
function to do this.)
Also, spamLatin should handle an initial 'y' either as a consonant
OR as a vowel, depending on whether the y is followed by a vowel
or consonant, respectively. For example, 'yes' has an initial y
acting as a consonant. The word 'yttrium', however -- element
#39 for anyone who's as chemically challenged as I am -- has an
initial y acting as a vowel. Here are some additional examples:
>>> spamLatin('string')
ingstray
>>> spamLatin('yttrium')
yttriumway
>>> spamLatin('yoohoo')
oohooyay
If you think about this problem thoroughly, you'll find that not every
possible case has been accounted for - you are free to decide the
appropriate course of action for those "corner cases."
Submitting your file
Page 23 of 26
You should submit your hw1ec1.py file at the Submission Site.
Extra Credit Option 2: Scoring papers (hw1ec2.py) [15 points, individual or
pair]
Week 1, Extra Problem 2: Scrabble-scoring your files...
[15 points; individual or pair]
This problem offers the chance to interact with files in Python. In
particular, it asks you to develop functions that will compute the
scrabble score of the text inside arbitrary files.
The function to write... scoreFile( fileName )
For this problem you should write a function named scoreFile(
fileName ) that takes in a string, which is the name of the file to
be scored. Then, your function should open that file, read its
contents, and compute the following:

The total scrabble score of all of the characters in the file.
Non-alphabetic characters get a score of 0. Both upper- and
lower-case letters, however, should count toward this total
according to their usual scrabble scores.

The total number of alphabetic characters in the file. This
includes both upper- and lower-case letters.

The average scrabble-score-per-letter for the file.
In particular, scoreFile should return a list of these three
quantities: the total score first, the number of letters second, and
the average score per letter third.
For example, here are our answers using the two files named
cow.txt and gburg.txt (downloadable below):
Page 24 of 26
>>> scoreFile( 'gburg.txt' )
[225, 143, 1.5734265734265733]
>>> scoreFile( 'cow.txt' )
[83, 45, 1.8444444444444446]
File handling in Python
File-handling is not too bad in Python. To get started, you might
want to download these two files to your desktop by right-clicking
each link (control-clicking on a Mac):
cow.txt, an Ogden Nash poem
gburg.txt, the preamble to the Gettysburg Address
Here is a function that illustrates how to open and extract the
contents of a file:
def printFileToScreen( fileName ):
""" simply prints the contents of the file to the
screen
input: fileName, a string with the file's name
"""
f = file( fileName ) # f is the opened file
text = f.read() # text is the name of all of f's text
f.close() # this closes the file f - a good idea
print 'The file contains:' # drumroll
print # blank line
print text # ta da!
You would be able to run this, as long as you're in the folder in
which the files are located, by invoking
>>> printFileToScreen( 'cow.txt' )
With any changes to the file name you'd like! Try this out, and then
modify the function above to begin implementing your scoreFile
function.
Page 25 of 26
Although this assignment does not require creating a file, here is an
example showing that it is not difficult to do:
#
# an example that creates (or overwrites) a file
#
def writeToFile( fileName ):
""" a function demonstrating how to create a new file
and
write to it. If the file (named fileName) already
exists, it will be overwritten
"""
f = file( fileName, 'w' ) # f is the file, opened for
writing
print >> f, "Hello there from Python!"
x = 42
print >> f, x, "is the number of tiles in a game of
scrabble."
f.close() # this closes the file f - a good idea
Running writeToFile('myfile.txt') produces no visible output,
but when you open the file myfile.txt, you'll see what was printed:
Hello there from Python!
42 is the number of tiles in a game of scrabble.
Handling large recursive calls
If you run scoreFile on files with more than 1,000 characters, it
may use more memory than Python allocates to the recursive stack
(and crash). To get around this, you can add the following lines at
the top of your hw1pr5.py file:
import sys
sys.setrecursionlimit(100000)
Page 26 of 26
These lines allow Python to build a stack of up to 100,000 function
calls -- or until the memory your operating system has given Python
runs out. Usually the latter happens first, leading to IDLE hanging
or crashing or producing the rather uninformative segmentation
fault error. However, you should at least be able to get well past
1,000 characters.
Testing this problem
In addition to writing the above scoreFile function -- which should
be in a file named hw1ec2.py, you should also run it on something
other than the two examples above: at least one additional file you
wrote (perhaps a hum paper) and another file of your choosing.
Don't use Microsoft Word-formatted files - they and other wordprocessed files have lots of formatting characters in them. Instead,
use plain-text files. Microsoft Word will reluctantly allow you to save
existing files to plain-text, though it will warn you with several
dialog boxes of the extreme risks you take by not using a Microsoft
file format!
In a comment at the top of your hw1ec2.py file, report the results
from the two files you chose.
Happy scrabbling!
Submitting your file
You should submit your hw1ec2.py file at the Submission Site.
Download