This is a short programming assignment in Python about dictionaries. I’ll need the txt and py file.
CS 112, Lab 9 – Exercise
Dictionaries, File I/O
(due Mon 11/5, 11:59pm)
Files:
•
•
•
Create your own file with our convention (userID_2xx_L9.py).
You should also download this file for testing:
http://cs.gmu.edu/~marks/112/labs/testerL9E.py
Run the tester as always: python3 testerL9E.py gmason76_2B5_L9.py just these funcs
As this is an Exercise, you can read any and all materials, ask us questions, talk with other students, and
learn however you best learn in order to solve the task. Just create your own solution from those
experiences, and turn in your work.
Reminder: you can run individual inputs, such as counts(“mississippi”), by loading your file into
interactive mode with the –i flag. You should be using this technique on projects as well.
demo$ python3 –i gmason_2B5_L9.py
>>> counts(“mississippi”)
{‘m’: 1, ‘p’: 2, ‘i’: 4, ‘s’: 4}
Dictionaries serve a special niche of problem type. Being able to pair up “keys” with “values”, and yet
disallowing duplicate entries with matching keys, helps us organize data by the exact keys we want to use
to initiate searching and inspecting our information.
We will solve some problems where perhaps there are solutions that could have been based upon lists,
but hopefully the dictionaries approach will make the task simpler.
Turning It In
Add a comment at the top of the file that indicates your name, userID, G#, lab section, a description of
your collaboration partners, as well as any other details you feel like sharing. Once you are done, run the
testing script once more to make sure you didn’t break things while adding these comments. If all is well,
go ahead and turn in just your one .py file you’ve been working on over on BlackBoard to the correct lab
assignment. We have our own copy of the testing file that we’ll use, so please don’t turn that in (or any
other extra files), as it will just slow us down.
What can I use?
There are no restrictions on what functions to use on this lab – use this time to learn how to build,
navigate, and modify dictionaries, and minimally how to read a file.
counts(xs): Consider a sequence of values, xs. It can contain duplicates, and we’d like to know how
many of each present value there are. Construct and return a dictionary whose keys are the things found
in the sequence, and whose corresponding values are the counts of occurrences.
• xs :: sequence of values. (It could be a list, a string, or other things…)
• Return value: a dictionary of things and their number of occurrences in xs.
• Examples:
o counts([1,1,1,2,3,3,3,3,5]) →
{1: 3, 2: 1, 3: 4, 5: 1}
o counts(“abracadabra”)
→
{‘r’: 2, ‘d’: 1, ‘c’: 1, ‘b’: 2, ‘a’: 5}
weeklies(plants_d): Consider a dictionary, plants_d, where the keys are names of plants, and the
values are descriptions of how often to water them. Search through the entire structure for all plants that
need to be watered “weekly”, put them into a list, sort() the list, and return it.
• plants_d :: dictionary of plant names to watering instructions.
• Return value: sorted list of plants that need watering “weekly”.
• >>> weeklies({‘shamrock’:’weekly’, ‘cactus’:’monthly’, ‘rose’:’weekly’, ‘succulent’:’biweekly’})
[‘rose’, ‘shamrock’]
•
>>> weeklies({‘fern’:’weekly’, ‘shamrock’:’weekly’, ‘carnation’:’weekly’})
[‘carnation’, ‘fern’, ‘shamrock’]
closest(d, what, here): Consider a dictionary that has pairs of integers as the keys, to represent a
spot on a 2D grid (like pixels on a screen or integer points on the real numbers plane). The associated
values will be strings, describing something that is present at that location. Using the distance formula
between two points (see Wikipedia for a refresher if needed), complete the closest function that looks
through the data for the spot closest to here that contains a what. For instance, “I’m at (2,3). Where’s the
closest gas station?” could be phrased as closest(d, “gas station”, (2,3)). Don’t worry about ties;
anything equally closest will do (but we’ll test with no ties to keep this short).
• Parameters:
o d :: dictionary where keys are pairs of integers and values are strings.
o what :: string describing a point of interest.
o here :: tuple of coordinates of where we currently are.
• Returns: a pair of integers of the closest what to here. When no what is found, return the None
value. (If we had learned about exceptions it would have been a great time for one here!)
• Examples:
o
>>> d = {(3,1):’gas’, (1,4):’gas’, (2,1):’food’, (5,5):’food’}
>>> closest(d,”gas”,(2,2))
#closest thing isn’t gas.
(3, 1)
>>> closest(d,”gas”,(5,5))
(1, 4)
>>> closest(d,”food”,(5,5))
(5, 5)
>>> closest(d,”food”,(1,4))
(2, 1)
>>> print(closest(d,”hotel”,(1,4)))
None
file_counts(filename): Re-implementation of the counts function that obtains a list
of numbers from a file. In the file, every single line will contain a single integer and
nothing else. The last character will be a newline.
• filename :: a string indicating the name of a file in the current directory.
• Return value: a dictionary of int as keys and # of occurrences as the values.
• file_counts(“file1.txt”)
→
{100:3, 3:1, 9:2}
• file_counts(“file2.txt”)
→
{1:1, 2:1, 3:1, 4:1, 5:1}
file1.txt
100
100
3
100
9
9
file2.txt
1
2
3
4
5
# Based on testing harness dated 2017-06-02.
# STUDENTS: TO USE:
#
# The following command will test all test cases on your file:
#
#
python3
#
#
# You can also limit the tester to only the functions you want tested.
# Just add as many functions as you want tested on to the command line at the
end.
# Example: to only run tests associated with func1 and func2, run this
command:
#
#
python3 func1 func2
#
# You really don’t need to read the file any further, except that when
# a specific test fails, you’ll get a line number – and it’s certainly
# worth looking at those areas for details on what’s being checked. This
would
# all be the indented block of code starting with “class AllTests”.
# INSTRUCTOR: TO PREPARE:
# – add test cases to class AllTests. The test case functions’ names must
# be precise – to test a function named foobar, the test must be named
“test_foobar_#”
# where # may be any digits at the end, such as “test_foobar_13”.
# – any extra-credit tests must be named “test_extra_credit_foobar_#”
#
# – name all required definitions in REQUIRED_DEFNS, and all extra credit
functions
#
in EXTRA_CREDIT_DEFNS. Do not include any unofficial helper functions. If
you want
#
to make helper definitions to use while testing, those can also be added
there for
#
clarity.
#
# – to run on either a single file or all .py files in a folder
(recursively):
#
python3
#
python3
#
python3 .
# current directory
#
# A work in progress by Mark Snyder, Oct. 2015.
# Edited by Yutao Zhong, Spring 2016.
# Edited by Raven Russell, Spring 2017.
# Edited by Mark Snyder, June 2017.
import
import
import
import
import
unittest
shutil
sys
os
time
#import subprocess
import importlib
############################################################################
############################################################################
# BEGIN SPECIALIZATION SECTION (the only part you need to modify beyond
# adding new test cases).
# name all expected definitions; if present, their definition (with correct
# number of arguments) will be used; if not, a decoy complainer function
# will be used, and all tests on that function should fail.
REQUIRED_DEFNS = [ “counts”, “weeklies”, “closest”, “file_counts” ]
# for method names in classes that will be tested
SUB_DEFNS = [ ]
# definitions that are used for extra credit
EXTRA_CREDIT_DEFNS = [ ]
# how many points are test cases worth?
weight_required = 4
weight_extra_credit = 1
# don’t count extra credit; usually 100% if this is graded entirely by tests.
# it’s up to you the instructor to do the math and add this up!
# TODO: auto-calculate this based on all possible tests.
total_points_from_tests = 100
# how many seconds to wait between batch-mode gradings?
# ideally we could enforce python to wait to open or import
# files when the system is ready but we’ve got a communication
# gap going on.
DELAY_OF_SHAME = 1
# set it to true when you run batch mode…
CURRENTLY_GRADING = False
# what temporary file name should be used for the student?
# This can’t be changed without hardcoding imports below, sorry.
# That’s kind of the whole gimmick here that lets us import from
# the command-line argument without having to qualify the names.
RENAMED_FILE = “student”
SECRET_FILE = “.tester_file.txt”
def write_secret_file(contents, name=SECRET_FILE):
f = open(name,”w”)
f.write(contents)
f.close()
# END SPECIALIZATION SECTION
############################################################################
############################################################################
# enter batch mode by giving a directory to work on as the only argument.
BATCH_MODE = len(sys.argv)==2 and (sys.argv[1] in [“.”] or
os.path.isdir(sys.argv[1]))
# This class contains multiple “unit tests” that each check
# various inputs to specific functions, checking that we get
# the correct behavior (output value) from completing the call.
class AllTests (unittest.TestCase):
######################################################################
######
# counts
def test_counts_1(self):
self.assertEqual(counts(“mississippi”),{‘m’:1, ‘p’:2, ‘i’:4, ‘s’:4})
def test_counts_2(self):
self.assertEqual(counts([1,1,1,2,3,3,3,3,5]),{1:3,2:1,3:4,5:1})
def test_counts_3(self):
self.assertEqual(counts([2,2,2,2,2,2,2]),{2:7})
def test_counts_4(self): self.assertEqual(counts([]),{})
def test_counts_5(self):
self.assertEqual(counts([1,2,3]),{1:1,2:1,3:1})
def test_counts_6(self): self.assertEqual(counts(“@”*100),{‘@’:100})
def test_counts_7(self):
self.assertEqual(counts(“abracadabra”),{‘r’:2,’d’:1,’c’:1,’b’:2,’a’:5})
# weeklies
def test_weeklies_1(self):
self.assertEqual(weeklies({‘shamrock’:’weekly’, ‘cactus’:’monthly’,
‘rose’:’weekly’, ‘succulent’:’biweekly’}),[‘rose’,’shamrock’])
def test_weeklies_2(self): self.assertEqual(weeklies({‘fern’:’weekly’,
‘shamrock’:’weekly’, ‘carnation’:’weekly’}),[‘carnation’,’fern’,’shamrock’])
def test_weeklies_3(self): self.assertEqual(weeklies({‘a’:’weekly’,
‘b’:’weekly’, ‘c’:’weekly’, ‘Z’:’weekly’, ‘x’:’weekly’}), [‘Z’, ‘a’, ‘b’,
‘c’, ‘x’])
def test_weeklies_4(self): self.assertEqual(weeklies({‘a’:’biweekly’,
‘b’:’weekly!!’, ‘weeds’:’never’}), [])
def test_weeklies_5(self):
self.assertEqual(weeklies({‘weekly’:’wrongplace’,’biweekly’:’baddata’}), [])
def test_weeklies_6(self): self.assertEqual(weeklies({}), [])
# closest
def test_closest_1(self): d = {(3,1):’gas’, (1,4):’gas’,
(5,5):’food’}; self.assertEqual(closest(d,’gas’,(2,2)),(3,1))
def test_closest_2(self): d = {(3,1):’gas’, (1,4):’gas’,
(5,5):’food’}; self.assertEqual(closest(d,’gas’,(5,5)),(1,4))
def test_closest_3(self): d = {(3,1):’gas’, (1,4):’gas’,
(5,5):’food’}; self.assertEqual(closest(d,’food’,(5,5)),(5,5))
def test_closest_4(self): d = {(3,1):’gas’, (1,4):’gas’,
(5,5):’food’}; self.assertEqual(closest(d,’food’,(1,4)),(2,1))
def test_closest_5(self): d = {(3,1):’gas’, (1,4):’gas’,
(5,5):’food’}; self.assertEqual(closest(d,’hotel’,(1,4)),None)
(2,1):’food’,
(2,1):’food’,
(2,1):’food’,
(2,1):’food’,
(2,1):’food’,
def test_closest_6(self): d = {(5,0):’gas’, (0,5):’gas’, (5,5):’gas’};
self.assertEqual(closest(d,’gas’,(3,3)),(5,5))
def test_closest_7(self): d = {};
self.assertEqual(closest(d,’gas’,(3,3)),None)
# file_closest
def test_file_counts_1(self):
write_secret_file(“1\n1\n1\n2\n3\n3\n3\n3\n5\n”);
self.assertEqual(file_counts(SECRET_FILE),{1:3,2:1,3:4,5:1})
def test_file_counts_2(self):
write_secret_file(“100\n100\n3\n100\n9\n9\n”);
self.assertEqual(file_counts(SECRET_FILE),{100:3, 3:1, 9:2})
def test_file_counts_3(self):
write_secret_file(“13\n13\n13\n13\n13\n13\n13\n13\n13\n13\n13\n13\n13\n13\n13
\n13\n”); self.assertEqual(file_counts(SECRET_FILE),{13:16})
def test_file_counts_4(self): write_secret_file(“-2\n”);
self.assertEqual(file_counts(SECRET_FILE),{-2:1})
def test_file_counts_5(self): write_secret_file(“”);
self.assertEqual(file_counts(SECRET_FILE),{})
######################################################################
######
# This class digs through AllTests, counts and builds all the tests,
# so that we have an entire test suite that can be run as a group.
class TheTestSuite (unittest.TestSuite):
# constructor.
def __init__(self,wants):
self.num_req = 0
self.num_ec = 0
# find all methods that begin with “test”.
fs = []
for w in wants:
for func in AllTests.__dict__:
# append regular tests
# drop any digits from the end of str(func).
dropnum = str(func)
while dropnum[-1] in “1234567890”:
dropnum = dropnum[:-1]
if dropnum==(“test_”+w+”_”) and (not
(dropnum==(“test_extra_credit_”+w+”_”))):
fs.append(AllTests(str(func)))
if dropnum==(“test_extra_credit_”+w+”_”) and
not BATCH_MODE:
fs.append(AllTests(str(func)))
#
print(“TTS ====> “,list(map(lambda f: (f,id(f)),fs)))
# call parent class’s constructor.
unittest.TestSuite.__init__(self,fs)
class TheExtraCreditTestSuite (unittest.TestSuite):
# constructor.
def __init__(self,wants):
# find all methods that begin with
“test_extra_credit_”.
fs = []
for w in wants:
for func in AllTests.__dict__:
if
str(func).startswith(“test_extra_credit_”+w):
fs.append(AllTests(str(func)))
#
print(“TTS ====> “,list(map(lambda f: (f,id(f)),fs)))
# call parent class’s constructor.
unittest.TestSuite.__init__(self,fs)
# all (non-directory) file names, regardless of folder depth,
# under the given directory ‘dir’.
def files_list(dir):
this_file = __file__
if dir==”.”:
dir = os.getcwd()
info = os.walk(dir)
filenames = []
for (dirpath,dirnames,filez) in info:
#
print(dirpath,dirnames,filez)
if dirpath==”.”:
continue
for file in filez:
if file==this_file:
continue
filenames.append(os.path.join(dirpath,file))
#
print(dirpath,dirnames,filez,”\n”)
return filenames
def main():
if len(sys.argv)0
# make sure they exist.
passed1 = 0
passed2 = 0
tried1 = 0
tried2 = 0
# only run tests if needed.
if has_reqs:
print(“\nRunning required definitions:”)
(tag, passed1,tried1) = run_file(sys.argv[1],wants,False)
if has_ec:
print(“\nRunning extra credit definitions:”)
(tag, passed2,tried2) =
run_file(sys.argv[1],extra_credits,True)
# print output based on what we ran.
if has_reqs and not has_ec:
print(“\n%d/%d Required test cases passed (worth %d each)” %
(passed1,tried1,weight_required) )
print(“\nScore based on test cases: %.2f/%d (%.2f*%d) ” % (
passed1*weight_required,
total_points_from_tests,
passed1,
weight_required
))
elif has_ec and not has_reqs:
print(“%d/%d Extra credit test cases passed (worth %d each)” %
(passed2, tried2, weight_extra_credit))
else: # has both, we assume.
print(“\n%d / %d Required test cases passed (worth %d each)” %
(passed1,tried1,weight_required) )
print(“%d / %d Extra credit test cases passed (worth %d each)”
% (passed2, tried2, weight_extra_credit))
print(“\nScore based on test cases: %.2f / %d ( %d * %d + %d *
%d) ” % (
passed1*weight_required+passed2*weight_extra_credit,
total_points_from_tests,
passed1,
weight_required,
passed2,
weight_extra_credit
))
if CURRENTLY_GRADING:
print(“( %d %d %d %d )\n%s” %
(passed1,tried1,passed2,tried2,tag))
# only used for batch mode.
def run_all():
filenames = files_list(sys.argv[1])
#print(filenames)
wants = REQUIRED_DEFNS + SUB_DEFNS
extra_credits = EXTRA_CREDIT_DEFNS
results = []
for filename in filenames:
print(” Batching on : ” +filename)
# I’d like to use subprocess here, but I can’t get it
to give me the output when there’s an error code returned… TODO for sure.
lines = os.popen(“python3 tester1p.py
\””+filename+”\””).readlines()
# delay of shame…
time.sleep(DELAY_OF_SHAME)
name = os.path.basename(lines[-1])
stuff =lines[-2].split(” “)[1:-1]
print(“STUFF: “,stuff, “LINES: “, lines)
(passed_req, tried_req, passed_ec, tried_ec) = stuff
results.append((lines[-1],int(passed_req),
int(tried_req), int(passed_ec), int(tried_ec)))
continue
print(“\n\n\nGRAND RESULTS:\n”)
for (tag_req, passed_req, tried_req, passed_ec, tried_ec) in
results:
name = os.path.basename(tag_req).strip()
earned
= passed_req*weight_required +
passed_ec*weight_extra_credit
possible = tried_req *weight_required # + tried_ec
*weight_extra_credit
print(“%10s : %3d / %3d = %5.2d %% (%d/%d*%d +
%d/%d*%d)” % (
name,
earned,
possible,
(earned/possible)*100,
passed_req,tried_req,weight_required,
passed_ec,tried_ec,weight_extra_credit
))
# only used for batch mode.
def run_all_orig():
filenames = files_list(sys.argv[1])
#print(filenames)
wants = REQUIRED_DEFNS + SUB_DEFNS
extra_credits = EXTRA_CREDIT_DEFNS
results = []
for filename in filenames:
# wipe out all definitions between users.
for fn in REQUIRED_DEFNS+EXTRA_CREDIT_DEFNS
globals()[fn] = decoy(fn)
fn = decoy(fn)
try:
name = os.path.basename(filename)
print(“\n\n\nRUNNING: “+name)
(tag_req, passed_req, tried_req) =
run_file(filename,wants,False)
(tag_ec, passed_ec, tried_ec ) =
run_file(filename,extra_credits,True)
:
results.append((tag_req,passed_req,tried_req,tag_ec,passed_ec,tried_ec
))
print(” ###### “, results)
except SyntaxError as e:
tag = filename+”_SYNTAX_ERROR”
results.append((tag,0,len(wants),tag,0,len(extra_credits)))
except NameError as e:
tag =filename+”_Name_ERROR”
results.append((tag,0,len(wants),tag,0,len(extra_credits)))
except ValueError as e:
tag = filename+”_VALUE_ERROR”
results.append((tag,0,len(wants),tag,0,len(extra_credits)))
except TypeError as e:
tag = filename+”_TYPE_ERROR”
results.append((tag,0,len(wants),tag,0,len(extra_credits)))
except ImportError as e:
tag = filename+”_IMPORT_ERROR_TRY_AGAIN”
results.append((tag,0,len(wants),tag,0,len(extra_credits)))
except Exception as e:
tag = filename+str(e.__reduce__()[0])
results.append((tag,0,len(wants),tag,0,len(extra_credits)))
#
#
#
#
#
try:
print(“\n |||||||||| scrupe: “+str(scruples))
except Exception as e:
print(“NO SCRUPE.”,e)
scruples = None
print(“\n\n\nGRAND RESULTS:\n”)
for (tag_req, passed_req, tried_req, tag_ec, passed_ec,
tried_ec) in results:
name = os.path.basename(tag_req)
earned
= passed_req*weight_required +
passed_ec*weight_extra_credit
possible = tried_req *weight_required # + tried_ec
*weight_extra_credit
print(“%10s : %3d / %3d = %5.2d %% (%d/%d*%d +
%d/%d*%d)” % (
name,
earned,
possible,
(earned/possible)*100,
passed_req,tried_req,weight_required,
passed_ec,tried_ec,weight_extra_credit
))
def try_copy(filename1, filename2, numTries):
have_copy = False
i = 0
while (not have_copy) and (i < numTries):
try:
# move the student's code to a valid file.
shutil.copy(filename1,filename2)
# wait for file I/O to catch up...
if(not wait_for_access(filename2, numTries)):
return False
have_copy = True
except PermissionError:
print("Trying to copy "+filename1+", may be locked...")
i += 1
time.sleep(1)
except BaseException as e:
print("\n\n\n\n\n\ntry-copy saw: "+e)
if(i == numTries):
return False
return True
def try_remove(filename, numTries):
removed = False
i = 0
while os.path.exists(filename) and (not removed) and (i < numTries):
try:
os.remove(filename)
removed = True
except OSError:
print("Trying to remove "+filename+", may be
locked...")
i += 1
time.sleep(1)
if(i == numTries):
return False
return True
def wait_for_access(filename, numTries):
i = 0
while (not os.path.exists(filename) or not os.access(filename,
os.R_OK)) and i < numTries:
print("Waiting for access to "+filename+", may be locked...")
time.sleep(1)
i += 1
if(i == numTries):
return False
return True
# this will group all the tests together, prepare them as
# a test suite, and run them.
def run_file(filename,wants=None,checking_ec = False):
if wants==None:
wants = []
# move the student's code to a valid file.
if(not try_copy(filename,"student.py", 5)):
print("Failed to copy " + filename + " to student.py.")
quit()
# import student's code, and *only* copy over the expected functions
# for later use.
import importlib
count = 0
while True:
try:
#
#
print("\n\n\nbegin attempt:")
while True:
try:
f = open("student.py","a")
f.close()
break
except:
pass
print ("\n\nSUCCESS!")
import student
importlib.reload(student)
break
except ImportError as e:
print("import error getting student... trying again.
"+os.getcwd(), os.path.exists("student.py"),e)
time.sleep(0.5)
while not os.path.exists("student.py"):
time.sleep(0.5)
count+=1
if count>3:
raise ImportError(“too many attempts at
importing!”)
except SyntaxError as e:
print(“SyntaxError in “+filename+”:\n”+str(e))
print(“Run your file without the tester to see the
details”)
return(filename+”_SYNTAX_ERROR”,None, None, None)
except NameError as e:
print(“NameError in “+filename+”:\n”+str(e))
print(“Run your file without the tester to see the
details”)
return((filename+”_Name_ERROR”,0,1))
except ValueError as e:
print(“ValueError in “+filename+”:\n”+str(e))
print(“Run your file without the tester to see the
details”)
return(filename+”_VALUE_ERROR”,0,1)
except TypeError as e:
print(“TypeError in “+filename+”:\n”+str(e))
print(“Run your file without the tester to see the
details”)
return(filename+”_TYPE_ERROR”,0,1)
except ImportError as e:
print(“ImportError in “+filename+”:\n”+str(e))
print(“Run your file without the tester to see the
details or try again”)
return((filename+”_IMPORT_ERROR_TRY_AGAIN
“,0,1))
except Exception as e:
print(“Exception in loading”+filename+”:\n”+str(e))
print(“Run your file without the tester to see the
details”)
return(filename+str(e.__reduce__()[0]),0,1)
# make a global for each expected definition.
for fn in REQUIRED_DEFNS+EXTRA_CREDIT_DEFNS
:
globals()[fn] = decoy(fn)
try:
globals()[fn] = getattr(student,fn)
except:
if fn in wants:
print(“\nNO DEFINITION FOR ‘%s’.” % fn)
if not checking_ec:
# create an object that can run tests.
runner = unittest.TextTestRunner()
# define the suite of tests that should be run.
suite = TheTestSuite(wants)
# let the runner run the suite of tests.
ans = runner.run(suite)
num_errors
= len(ans.__dict__[‘errors’])
num_failures = len(ans.__dict__[‘failures’])
num_tests
= ans.__dict__[‘testsRun’]
num_passed
= num_tests – num_errors – num_failures
# print(ans)
else:
# do the same for the extra credit.
runner = unittest.TextTestRunner()
suite = TheExtraCreditTestSuite(wants)
ans = runner.run(suite)
num_errors
= len(ans.__dict__[‘errors’])
num_failures = len(ans.__dict__[‘failures’])
num_tests
= ans.__dict__[‘testsRun’]
num_passed
= num_tests – num_errors – num_failures
#print(ans)
# remove our temporary file.
os.remove(“student.py”)
if os.path.exists(“__pycache__”):
shutil.rmtree(“__pycache__”)
if(not try_remove(“student.py”, 5)):
print(“Failed to remove ” + filename + ” to student.py.”)
tag = “.”.join(filename.split(“.”)[:-1])
return (tag, num_passed, num_tests)
# make a global for each expected definition.
def decoy(name):
# this can accept any kind/amount of args, and will print a
helpful message.
def failyfail(*args, **kwargs):
return (“” % name)
return failyfail
# this determines if we were imported (not __main__) or not;
# when we are the one file being run, perform the tests! 🙂
if __name__ == “__main__”:
main()
(due Mon 11/5, 11:59pm)
CS 112, Lab 9 – Exercise
Dictionaries, File I/O
Files:
.
Create your own file with our convention (userID_2xx_L9.py).
You should also download this file for testing: http://cs.gmu.edu/-marks/112/labs/testerL9E.py
Run the tester as always: python3 testerL9E.py gmason76_2B5_L9.py just these funcs
As this is an Exercise, you can read any and all materials, ask us questions, talk with other students, and
learn however you best learn in order to solve the task. Just create your own solution from those
experiences, and turn in your work.
Reminder: you can run individual inputs, such as counts(“mississippi”), by loading your file into
interactive mode with the -i flag. You should be using this technique on projects as well.
demo$ python3 -i gmason_285_L9.py
>>> counts(“mississippi”)
{‘m’: 1, ‘p’: 2, ‘i’: 4, ‘s’: 4}
Dictionaries serve a special niche of problem type. Being able to pair up “keys” with “values”, and yet
disallowing duplicate entries with matching keys, helps us organize data by the exact keys we want to use
to initiate searching and inspecting our information.
We will solve some problems where perhaps there are solutions that could have been based upon lists,
but hopefully the dictionaries approach will make the task simpler.
Turning It In
Add a comment at the top of the file that indicates your name, userID, G#, lab section, a description of
your collaboration partners, as well as any other details you feel like sharing. Once you are done, run the
testing script once more to make sure you didn’t break things while adding these comments. If all is well,
go ahead and turn in just your one.py file you’ve been working on over on BlackBoard to the correct lab
assignment. We have our own copy of the testing file that we’ll use, so please don’t turn that in (or any
other extra files), as it will just slow us down.
What can I use?
There are no restrictions on what functions to use on this lab – use this time to learn how to build,
navigate, and modify dictionaries, and minimally how to read a file.
counts(xs): Consider a sequence of values, xs. It can contain duplicates, and we’d like to know how
many of each present value there are. Construct and return a dictionary whose keys are the things found
in the sequence, and whose corresponding values are the counts of occurrences.
xs :: sequence of values. (It could be a list, a string, or other things…)
Return value: a dictionary of things and their number of occurrences in xs.
Examples:
counts([1,1,1,2,3,3,3,3,5])
{1: 3, 2: 1, 3: 4, 5: 1}
counts (“abracadabra”)
{‘r’: 2, ‘d’: 1, ‘c’: 1, ‘b’: 2, ‘a’: 5}
O
o
weeklies (plants_d): Consider a dictionary, plants_d, where the keys are names of plants, and the
values are descriptions of how often to water them. Search through the entire structure for all plants that
need to be watered “weekly”, put them into a list, sort() the list, and return it.
• plants_d :: dictionary of plant names to watering instructions.
Return value: sorted list of plants that need watering “weekly”.
>>> weeklies({‘ shamrock’:’weekly’, ‘cactus’:’monthly’, ‘rose’: ‘weekly’, ‘succulent’:’biweekly’})
[‘rose’, ‘shamrock’]
>>> weeklies({‘fern’: ‘weekly’, ‘shamrock’:’weekly’, ‘carnation’:’weekly’ })
[‘carnation’, ‘fern’, ‘shamrock’]
O
closest(d, what, here): Consider a dictionary that has pairs of integers as the keys, to represent a
spot on a 2D grid (like pixels on a screen or integer points on the real numbers plane). The associated
values will be strings, describing something that is present at that location. Using the distance formula
between two points (see Wikipedia for a refresher if needed), complete the closest function that looks
through the data for the spot closest to here that contains a what. For instance, “I’m at (2,3). Where’s the
closest gas station?” could be phrased as closest(d, “gas station”, (2,3)). Don’t worry about ties;
anything equally closest will do (but we’ll test with no ties to keep this short).
Parameters:
od: dictionary where keys are pairs of integers and values are strings.
what :: string describing a point of interest.
here :: tuple of coordinates of where we currently are.
Returns: a pair of integers of the closest what to here. When no what is found, return the None
value. (If we had learned about exceptions it would have been a great time for one here!)
Examples:
>>> d = {(3,1):’gas’, (1,4):’gas’, (2,1):’food’, (5,5):’food’}
>>> closest(d,”gas”, (2, 2)) #closest thing isn’t gas.
(3, 1)
>>> closest(d, “gas”,(5,5))
(1,4)
>>> closest(d,”food”, (5,5))
(5, 5)
>>> closest(d, “food”,(1,4))
(2, 1)
>>> print(closest(d, “hotel”,(1,4)))
None
o
file_counts(filename): Re-implementation of the counts function that obtains a list
of numbers from a file. In the file, every single line will contain a single integer and
nothing else. The last character will be a newline.
filename :: a string indicating the name of a file in the current directory.
Return value: a dictionary of int as keys and # of occurrences as the values.
file_counts(“file1.txt”)
{100:3, 3:1, 9:2}
file_counts(“file2.txt”)
{1:1, 2:1, 3:1, 4:1, 5:1}
.
file1.txt file2.txt
100 1
100 2
3
3
100 4
9
5
9
.
.