Difference between revisions of "CSC111 Homework 6 2015"
(2 intermediate revisions by the same user not shown) | |||
Line 10: | Line 10: | ||
=Preparation= | =Preparation= | ||
<br /> | <br /> | ||
− | * Create a program called '''testHw6.py''' with the code available on [http://cs.smith.edu/dftwiki/index.php | + | * Create a program called '''testHw6.py''' with the code available on [http://cs.smith.edu/dftwiki/index.php/CSC111_testHw6.py_2015 this page]. Save it in the same place where you will store your '''hw6.py''' program. |
* Create a second program, called '''hw6.py'''. This program will contain all the functions that you are asked to write for this assignment. Add the code below to your '''hw6.py''' code: | * Create a second program, called '''hw6.py'''. This program will contain all the functions that you are asked to write for this assignment. Add the code below to your '''hw6.py''' code: | ||
<br /> | <br /> | ||
Line 201: | Line 201: | ||
<br /> | <br /> | ||
− | <showafterdate after=" | + | <showafterdate after="20150313 00:00" before="20150601 00:00"> |
<br /> | <br /> | ||
=Solution Program= | =Solution Program= | ||
Line 309: | Line 309: | ||
</source> | </source> | ||
<br /> | <br /> | ||
+ | </showafterdate> | ||
<br /> | <br /> | ||
<onlydft> | <onlydft> | ||
=VPL Module= | =VPL Module= | ||
+ | <br /> | ||
+ | |||
+ | ==vpl_run.sh== | ||
+ | <br /> | ||
+ | <source lang="bash"> | ||
+ | #! /bin/bash | ||
+ | |||
+ | cat > vpl_execution <<EOF | ||
+ | #! /bin/bash | ||
+ | |||
+ | # --- Python ---- | ||
+ | if [[ `hostname -s` = "beowulf2" ]]; then | ||
+ | python=/usr/bin/python3.3 | ||
+ | else | ||
+ | python=/usr/local/bin/python3.4 | ||
+ | fi | ||
+ | |||
+ | prog=testHw6.py | ||
+ | \$python \$prog | ||
+ | |||
+ | EOF | ||
+ | |||
+ | chmod +x vpl_execution | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | ==vpl_debug.sh== | ||
+ | <br /> | ||
+ | <source lang="bash"> | ||
+ | </source> | ||
+ | <br /> | ||
+ | ==vpl_evaluate.sh== | ||
+ | <br /> | ||
+ | <source lang="bash"> | ||
+ | #! /bin/bash | ||
+ | |||
+ | cat > vpl_execution <<EOF | ||
+ | #! /bin/bash | ||
+ | |||
+ | # --- Python ---- | ||
+ | if [[ `hostname -s` = "beowulf2" ]]; then | ||
+ | python=/usr/bin/python3.3 | ||
+ | else | ||
+ | python=/usr/local/bin/python3.4 | ||
+ | fi | ||
+ | |||
+ | |||
+ | |||
+ | \$python evaluate.py | ||
+ | cat log.txt | ||
+ | |||
+ | EOF | ||
+ | |||
+ | chmod +x vpl_execution | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | ==vpl_evaluate.cases== | ||
+ | <br /> | ||
+ | <source lang="text"> | ||
+ | </source> | ||
+ | <br /> | ||
+ | ==evaluate.py== | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | # evaluate.py | ||
+ | # D. Thiebaut | ||
+ | # This program is used to test a student's python program on Moodle. | ||
+ | |||
+ | import sys | ||
+ | import random | ||
+ | import subprocess | ||
+ | |||
+ | #--- GLOBALS --- | ||
+ | #--- define what the student program is called, and what the solution | ||
+ | #--- program name is. | ||
+ | |||
+ | |||
+ | module = "testHw6" | ||
+ | solutionModule = module + "sol" | ||
+ | userOutSplitPattern = "" # pattern used to start recording the user | ||
+ | # output. Useful when program does several | ||
+ | # input() statements, and user output starts | ||
+ | # after that. | ||
+ | stripOutputsBeforeCompare = True | ||
+ | # set to True if extra spaces at beginning or | ||
+ | # end of user output is ok | ||
+ | |||
+ | interpreter = sys.executable | ||
+ | |||
+ | def commentLong( line ): | ||
+ | print( "<|--\n" + line + "\n --|>" ) | ||
+ | |||
+ | def commentShort( text ): | ||
+ | print( "Comment :=>> " + text ) | ||
+ | |||
+ | def printGrade( grade ): | ||
+ | print( "Grade :=>> ", grade ) | ||
+ | |||
+ | # generateInputFileWithRandomInputs | ||
+ | # generate a file with name "inputFileName" with some random input | ||
+ | # for the program. | ||
+ | # MAKE SURE TO EDIT THIS TO MATCH THE PROGRAM BEING TESTED | ||
+ | def generateInputFileWithRandomInputs( inputFileName ): | ||
+ | #--- we don't need an input file for stdin, but we'll generate a | ||
+ | #--- dummy one nonetheless | ||
+ | open( inputFileName, "w" ).write( "\n\n\n\n\n\n\n" ) | ||
+ | |||
+ | #--- generate random inputs --- | ||
+ | return "\n" | ||
+ | |||
+ | # checkForFunctionPresence | ||
+ | # checks that "functionName" is defined and called in the program. | ||
+ | # MAKE SURE TO EDIT TO MATCH PROGRAM BEING TESTED | ||
+ | def checkForFunctionPresence( module, functionName ): | ||
+ | foundDef = False | ||
+ | foundCall = False | ||
+ | |||
+ | for line in open( module+".py", "r" ).readlines(): | ||
+ | # remove comments | ||
+ | idx = line.find( "#" ) | ||
+ | if ( idx >=0 ): line = line[0:idx] | ||
+ | |||
+ | if line.startswith( "def " + functionName + "(" ): | ||
+ | foundDef = True | ||
+ | continue | ||
+ | if line.startswith( "def " + functionName + " (" ): | ||
+ | foundDef = True | ||
+ | continue | ||
+ | if line.find( functionName+"(" ) != -1: | ||
+ | foundCall = True | ||
+ | continue | ||
+ | |||
+ | return (foundDef, foundCall) | ||
+ | |||
+ | |||
+ | |||
+ | # ================================================================== | ||
+ | # NO EDITS NEEDED BELOW! | ||
+ | # ================================================================== | ||
+ | |||
+ | def clearLog(): | ||
+ | open( "log.txt", "w" ).write( "" ) | ||
+ | |||
+ | def log( message ): | ||
+ | file = open( "log.txt", "a" ) | ||
+ | file.write( message + "\n" ) | ||
+ | file.flush() | ||
+ | file.close() | ||
+ | |||
+ | |||
+ | # checkModuleRunsOK: runs the module as a shell subprocess and | ||
+ | # look for errors in the output. This is required, because otherwise | ||
+ | # importing the module in this program will make this program crash. | ||
+ | # It's not possible (as far as I can tell0 to catch exceptions from | ||
+ | # the import or __module__ statements. | ||
+ | # returns True, none if no errors, otherwise False, string if there's | ||
+ | # an exception, and the error message (string) is in the returned 2nd | ||
+ | # arg. | ||
+ | # The module name is assumed to not include ".py" | ||
+ | def checkModuleRunsOk( module, inputFileName ): | ||
+ | global interpreter | ||
+ | p = subprocess.Popen( [ interpreter, module+".py" ], | ||
+ | stdout=subprocess.PIPE, | ||
+ | stderr=subprocess.PIPE, | ||
+ | stdin=subprocess.PIPE) | ||
+ | |||
+ | #print( "inputFileName = ", inputFileName ) | ||
+ | #print( "open( inputFileName, r).read() = ", open( inputFileName, "r" ).read() ) | ||
+ | |||
+ | p.stdin.write( bytes( open( inputFileName, "r" ).read(), 'UTF-8' ) ) | ||
+ | data = p.communicate( ) | ||
+ | p.stdin.close() | ||
+ | |||
+ | error = data[1].decode( 'UTF-8' ) | ||
+ | if len( error ) > 1: | ||
+ | return False, error | ||
+ | return True, None | ||
+ | |||
+ | |||
+ | # extractTextFromErrorMessage( sys_exc_info ): | ||
+ | def extractTextFromErrorMessage( sys_exc_info ): | ||
+ | print( "sys_exec_info = ", sys_exc_info ) | ||
+ | text = "" | ||
+ | for field in sys_exc_info: | ||
+ | if type( field )==type( " " ): | ||
+ | text += field + "\n" | ||
+ | return text | ||
+ | |||
+ | # runModule: | ||
+ | # runs the module, passes it data from the input file on its stdin | ||
+ | # and get its output on stdout captured in outputFileName. | ||
+ | # We assume the module will not crash, because we already tested | ||
+ | # it with checkModuleRunsOk(). | ||
+ | def runModule( module, inputFileName, outputFileName ): | ||
+ | global userOutSplitPattern | ||
+ | |||
+ | error = False | ||
+ | |||
+ | #--- make stdin read information from the text file | ||
+ | sys.stdin = open( inputFileName, "r" ) | ||
+ | |||
+ | #--- capture the stdout of the program to test into a file | ||
+ | saveStdOut = sys.stdout | ||
+ | saveStdErr = sys.stderr | ||
+ | |||
+ | sys.stdout = open( outputFileName, "w" ) | ||
+ | sys.stderr = open( "errorOut", "w" ) | ||
+ | |||
+ | #--- run the student program --- | ||
+ | try: | ||
+ | _module = __import__( module ) | ||
+ | except: | ||
+ | error = True | ||
+ | sys.stderr.close() | ||
+ | sys.stderr = saveStdErr | ||
+ | sys.stdout.close() | ||
+ | sys.stdout = saveStdOut | ||
+ | text = sys.exc_info()[0] | ||
+ | text = extractTextFromErrorMessage( text ) | ||
+ | #print( "*** sys.exc_info() = ", text ) | ||
+ | text = open( outputFileName, "r" ).read() + "\n" + text | ||
+ | return error, text | ||
+ | |||
+ | #--- filter out junk from output of program --- | ||
+ | sys.stdout.close() | ||
+ | sys.stdout = saveStdOut | ||
+ | sys.stderr.close() | ||
+ | sys.stderr = saveStdErr | ||
+ | |||
+ | file = open( outputFileName, "r" ) | ||
+ | text = file.read() | ||
+ | score = 0 | ||
+ | for line in text.split( "\n" ): | ||
+ | if line.find( "out" ) != -1: | ||
+ | words = line.split( " " ) | ||
+ | for i in range( len( words ) ): | ||
+ | if words[i]=="out": | ||
+ | #print( "words[i-1] =|%s|" % words[i-1] ) | ||
+ | try: | ||
+ | score += int( words[i-1] ) | ||
+ | except: | ||
+ | pass | ||
+ | |||
+ | #print( text, end="" ) | ||
+ | file.close() | ||
+ | return False, text, score | ||
+ | |||
+ | def removeBlankLines( lines ): | ||
+ | newLines = [] | ||
+ | log( "removeBlankLines: lines = " + str( lines ) ) | ||
+ | for line in lines.split( "\n" ): | ||
+ | if len( line )==0: | ||
+ | continue | ||
+ | newLines.append( line ) | ||
+ | |||
+ | return ( "\n".join( newLines ) ) + "\n" | ||
+ | |||
+ | def compareUserExpected( inputLines, userOutText, expectedOutText ): | ||
+ | global stripOutputsBeforeCompare | ||
+ | |||
+ | log( "userOutText = " + userOutText ) | ||
+ | log( "expectedOutText = " + expectedOutText ) | ||
+ | |||
+ | userOutText = removeBlankLines( userOutText ) | ||
+ | expectedOutText = removeBlankLines( expectedOutText ) | ||
+ | misMatchLineNumbers = [] | ||
+ | userTextOutLines = userOutText.split( "\n" ) | ||
+ | expectedOutTextLines = expectedOutText.split( "\n" ) | ||
+ | |||
+ | log( "-" * 60 ) | ||
+ | log( "userTextOutLines = " + str( userTextOutLines ) ) | ||
+ | log( "expectedOutTextLines = " + str( expectedOutTextLines ) ) | ||
+ | log( "-" * 60 ) | ||
+ | |||
+ | for i in range( len( userTextOutLines ) ): | ||
+ | lineNo = i+1 | ||
+ | userLine = userTextOutLines[i] | ||
+ | if i >= len( expectedOutTextLines ): | ||
+ | misMatchLineNumbers.append( lineNo ) | ||
+ | break | ||
+ | expectedLine = expectedOutTextLines[i] | ||
+ | log( "comparing:\n "+userLine+"\n "+expectedLine ) | ||
+ | if stripOutputsBeforeCompare: | ||
+ | userLine = userLine.strip() | ||
+ | expectedLine = expectedLine.strip() | ||
+ | if userLine != expectedLine: | ||
+ | log( "\ndifference: user >" + userTextOutLines[i] + "<" ) | ||
+ | log( "expected >" + expectedOutTextLines[i] + "<" ) | ||
+ | misMatchLineNumbers.append( lineNo ) | ||
+ | |||
+ | return misMatchLineNumbers | ||
+ | |||
+ | |||
+ | |||
+ | def main(): | ||
+ | global module | ||
+ | global solutionModule | ||
+ | |||
+ | #--- clear debug log --- | ||
+ | clearLog() | ||
+ | |||
+ | #--- check that the main module uses a main() function | ||
+ | foundDef, foundCall = checkForFunctionPresence( module, "main" ) | ||
+ | """ | ||
+ | if (not foundDef) or (not foundCall): | ||
+ | commentShort( "-Missing main() program" ) | ||
+ | commentShort( "Your program must use a main() function." ) | ||
+ | commentShort( "(make sure you spell it exactly \"main()\"!" ) | ||
+ | printGrade( 40 ) | ||
+ | return | ||
+ | """ | ||
+ | |||
+ | #--- generate input file with random data --- | ||
+ | inputLines = generateInputFileWithRandomInputs( "input" ) | ||
+ | |||
+ | |||
+ | Ok, errorMessage = checkModuleRunsOk( module, "input" ) | ||
+ | if not Ok: | ||
+ | commentLong( "- Your program crashed...\n" | ||
+ | + "Error message:\n" | ||
+ | + errorMessage + "\n" ) | ||
+ | printGrade( 50 ) | ||
+ | return | ||
+ | |||
+ | |||
+ | error, userOutText, score = runModule( module, "input", "userOut" ) | ||
+ | if error: | ||
+ | commentLong( "- Your program crashed...\n" | ||
+ | + "Your program was tested with files containing:\n" | ||
+ | + inputLines + "\n" | ||
+ | + "Error message:\n" | ||
+ | + userOutText + "\n" ) | ||
+ | printGrade( 53 + score) | ||
+ | return | ||
+ | |||
+ | commentLong( "- Output of the test program:\n" + userOutText ) | ||
+ | printGrade( 53 + score ) | ||
+ | |||
+ | main() | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | ==testHw6.py== | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | # testHw6.py | ||
+ | # D. Thiebaut | ||
+ | # This program tests all the functions for Homework 6. | ||
+ | # To use this program, simply write a program called hw6.py and | ||
+ | # store your functions in it. The functions are expected to be | ||
+ | # named function1(), function2(), etc. | ||
+ | # To test the the function, simply make sure that test6.py and | ||
+ | # hw6.py are in the same directory, and run test6.py. It will | ||
+ | # automatically import hw6.py and call the different functions, | ||
+ | # passing them parameters and checking the values returned by | ||
+ | # the functions. | ||
+ | |||
+ | import random # that's the module that allows us to pick random quantities | ||
+ | import hw6 # that's your hw6.py module. We don't add ".py" to modules, | ||
+ | # but the file containing the program must have ".py" at the end. | ||
+ | |||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | # compares 2 lists an indicate if they are identical. Prints | ||
+ | # information about differences that may exist. | ||
+ | def compare2Lists( functionName, userList, expectedList, listType ): | ||
+ | # same type? | ||
+ | if type( userList ) != type( expectedList ): | ||
+ | print( functionName, "does not return a list of", listType ) | ||
+ | return 0 | ||
+ | |||
+ | # same length? | ||
+ | if len( userList ) != len( expectedList ): | ||
+ | print( functionName, "returns the wrong number of items in the list" ) | ||
+ | print( len( expectedList ), "items are expected, but", | ||
+ | len( userList ), "are returned." ) | ||
+ | return 0 | ||
+ | |||
+ | # same items in the list? | ||
+ | noMatching = 0 | ||
+ | for i in range( len( userList ) ): | ||
+ | if userList[i] == expectedList[i]: | ||
+ | noMatching = noMatching + 1 | ||
+ | else: | ||
+ | print( functionName + ": mismatch at Index", i, | ||
+ | userList[i], "found instead of", expectedList[i] ) | ||
+ | |||
+ | return noMatching/len( userList ) | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction0(): | ||
+ | try: | ||
+ | score, total = testFunction0b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function0 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | def testFunction0b(): | ||
+ | names = [ " HELLO there!", " !", " ! ", " :-) " ] | ||
+ | noTests = len( names ) | ||
+ | |||
+ | numberGood = 0 | ||
+ | for i in range( noTests ): | ||
+ | name = names[i] | ||
+ | expected = "**{0:1}**".format( name.title().strip() ) | ||
+ | |||
+ | userOut = hw6.function0( name ) | ||
+ | |||
+ | if type( userOut ) != type( expected ): | ||
+ | print( "function0 does not return a string. 0 out of 4." ) | ||
+ | return 0, 4 | ||
+ | if expected == userOut: | ||
+ | numberGood = numberGood + 1 | ||
+ | else: | ||
+ | print( "function0 returns", userOut, "instead of", expected + "." ) | ||
+ | |||
+ | print( "Function 0 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction1(): | ||
+ | try: | ||
+ | score, total = testFunction1b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function1 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | def testFunction1b(): | ||
+ | celsiusTemps = [ -10, 0, 11, 40 ] | ||
+ | expected = [14.0, 32.0, 51.8, 104.0] | ||
+ | numberGood = 0 | ||
+ | noTests = len( expected ) | ||
+ | |||
+ | for i in range( noTests ): | ||
+ | celsius = celsiusTemps[ i ] | ||
+ | fahr = hw6.function1( celsius ) | ||
+ | if ( fahr == expected[ i ] ): | ||
+ | numberGood = numberGood + 1 | ||
+ | |||
+ | print( "Function 1 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction2(): | ||
+ | try: | ||
+ | score, total = testFunction2b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function2 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | |||
+ | def testFunction2b(): | ||
+ | celsiusTemps = [ -10, 0, 9, 40 ] | ||
+ | expected = [ 14, 32, 48, 104 ] | ||
+ | numberGood = 0 | ||
+ | noTests = len( expected ) | ||
+ | |||
+ | for i in range( noTests ): | ||
+ | celsius = celsiusTemps[ i ] | ||
+ | fahr = hw6.function2( celsius ) | ||
+ | #print( fahr ) | ||
+ | if type( fahr ) != type( 3 ): | ||
+ | print( "Function 2 does not return an int" ) | ||
+ | elif fahr != expected[ i ]: | ||
+ | print( "Function 2's output is incorrect for", celsius ) | ||
+ | else: | ||
+ | numberGood = numberGood + 1 | ||
+ | |||
+ | print( "Function 2 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction3(): | ||
+ | try: | ||
+ | score, total = testFunction3b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function3 does not exist or crashed. 0 out of 3 points." ) | ||
+ | return 0, 3 | ||
+ | |||
+ | def testFunction3b(): | ||
+ | phoneStrings = [ "(413) 555 1212", "(617) 111 2233", | ||
+ | "(919) 777 1234" ] | ||
+ | expected = [ "555 1212", "111 2233", "777 1234" ] | ||
+ | numberGood = 0 | ||
+ | noTests = len( expected ) | ||
+ | |||
+ | for i in range( noTests ): | ||
+ | longPhone = phoneStrings[ i ] | ||
+ | phone = hw6.function3( longPhone ) | ||
+ | |||
+ | if type( phone ) != type( "111 2233" ): | ||
+ | print( "Function 3 does not return a string" ) | ||
+ | elif phone != expected[ i ]: | ||
+ | print( "Function 3's output is incorrect for", longPhone ) | ||
+ | else: | ||
+ | numberGood = numberGood + 1 | ||
+ | |||
+ | print( "Function 3 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction4(): | ||
+ | try: | ||
+ | score, total = testFunction4b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function4 does not exist or crashed. 0 out of 3 points." ) | ||
+ | return 0, 3 | ||
+ | |||
+ | def testFunction4b(): | ||
+ | phoneStrings = [ "The phone is (413) 555 1212.", "+1 (617) 111 2233 is my phone", | ||
+ | "Dial (413) 585 2700 for Smith College" ] | ||
+ | expected = [ "The phone is (XXX) 555 1212.", "+1 (XXX) 111 2233 is my phone", | ||
+ | "Dial (XXX) 585 2700 for Smith College" ] | ||
+ | numberGood = 0 | ||
+ | noTests = len( expected ) | ||
+ | |||
+ | for i in range( noTests ): | ||
+ | longPhone = phoneStrings[ i ] | ||
+ | phone = hw6.function4( longPhone ) | ||
+ | |||
+ | if type( phone ) != type( "111 2233" ): | ||
+ | print( "Function 4 does not return a string" ) | ||
+ | elif phone != expected[ i ]: | ||
+ | print( "Function 4's output is incorrect for", longPhone ) | ||
+ | else: | ||
+ | numberGood = numberGood + 1 | ||
+ | |||
+ | print( "Function 4 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction5(): | ||
+ | try: | ||
+ | score, total = testFunction5b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function5 does not exist or crashed. 0 out of 3 points." ) | ||
+ | return 0, 3 | ||
+ | |||
+ | def testFunction5b(): | ||
+ | lines = [ "My Id is 990111222. Yours?", | ||
+ | "990999999 is the ID.", | ||
+ | "The best student in the race has Id 990112233" ] | ||
+ | |||
+ | expected= [ "My Id is 990123456. Yours?", | ||
+ | "990123456 is the ID.", | ||
+ | "The best student in the race has Id 990123456" ] | ||
+ | |||
+ | numberGood = 0 | ||
+ | noTests = len( expected ) | ||
+ | |||
+ | for i in range( noTests ): | ||
+ | line = lines[ i ] | ||
+ | anonym = hw6.function5( line ) | ||
+ | |||
+ | #print( line ) | ||
+ | #print( anonym ) | ||
+ | |||
+ | if type( anonym ) != type( "111 2233" ): | ||
+ | print( "Function 5 does not return a string" ) | ||
+ | elif anonym != expected[ i ]: | ||
+ | print( "Function 5's output is incorrect for", line ) | ||
+ | else: | ||
+ | numberGood = numberGood + 1 | ||
+ | |||
+ | print( "Function 5 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction6(): | ||
+ | try: | ||
+ | score, total = testFunction6b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function6 does not exist or crashed. 0 out of 3 points." ) | ||
+ | return 0, 3 | ||
+ | |||
+ | def testFunction6b(): | ||
+ | numberGood = 0 | ||
+ | noTests = 3 | ||
+ | for i in range( noTests ): | ||
+ | expected1 = random.choice( [ "first line", "premiere ligne", "01 LINE 1" ] ) | ||
+ | file = open( "file1.txt", "w" ) | ||
+ | file.write( expected1 + "\nsecond line\nthird line." ) | ||
+ | file.close() | ||
+ | |||
+ | line1 = hw6.function6( "file1.txt" ) | ||
+ | if type( line1 ) != type( "hello" ): | ||
+ | print( "Function 6 does not return a string" ) | ||
+ | elif line1 != expected1: | ||
+ | print( "Function 6 returns the wrong line: " + line1 ) | ||
+ | else: | ||
+ | numberGood = numberGood + 1 | ||
+ | |||
+ | print( "Function 6 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction7(): | ||
+ | try: | ||
+ | score, total = testFunction7b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function7 does not exist or crashed. 0 out of 3 points." ) | ||
+ | return 0, 3 | ||
+ | |||
+ | def testFunction7b(): | ||
+ | numberGood = 0 | ||
+ | noTests = 3 | ||
+ | |||
+ | # test 3 times | ||
+ | for i in range( noTests ): | ||
+ | # pick a random name for the file | ||
+ | fileName = random.choice( [ "lines.txt", "dataFile.txt", "file.data" ] ) | ||
+ | |||
+ | # pick a last line to put at the end of the file | ||
+ | expected1 = random.choice( [ " IT IS THE LAST LINE!!", | ||
+ | "Last in file!", "DERNIERE LIGNE" ] ) | ||
+ | |||
+ | # write the test file | ||
+ | file = open( fileName, "w" ) | ||
+ | file.write( "\nSecond line of file\nSecond line\n" + expected1 ) | ||
+ | file.close() | ||
+ | |||
+ | # get the line returned by function 7 in hw6.py | ||
+ | line1 = hw6.function7( fileName ) | ||
+ | |||
+ | # test if correct | ||
+ | if type( line1 ) != type( "hello" ): | ||
+ | print( "Function 7 does not return a string" ) | ||
+ | elif line1 != expected1: | ||
+ | print( "Function 7 returns the wrong line: " + line1 ) | ||
+ | else: | ||
+ | numberGood = numberGood + 1 | ||
+ | |||
+ | print( "Function 7 passes", numberGood, "out of", noTests, "tests." ) | ||
+ | return numberGood, noTests | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction8(): | ||
+ | try: | ||
+ | score, total = testFunction8b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function8 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | def testFunction8b(): | ||
+ | numberGood = 0 | ||
+ | noTests = 3 | ||
+ | |||
+ | # pick a random name for the file | ||
+ | fileName = random.choice( [ "lines.txt", "dataFile.txt", "file.data" ] ) | ||
+ | |||
+ | # | ||
+ | text = "" | ||
+ | for i in range( 4 ): | ||
+ | text = text + random.choice( [ "Good job!\n", "Great game of go today!\n", | ||
+ | "George gest going in the fog\n", | ||
+ | "Simple line\n", "g\n" ] ) | ||
+ | |||
+ | # write the test file | ||
+ | file = open( fileName, "w" ) | ||
+ | file.write( text ) | ||
+ | file.close() | ||
+ | |||
+ | # get the line returned by function 7 in hw6.py | ||
+ | userText = hw6.function8( fileName ) | ||
+ | #print( "userText = ", userText ) | ||
+ | |||
+ | expected = text.replace( 'g', 'gremlin' ) | ||
+ | expected = expected.replace( 'G', 'Gremlin' ) | ||
+ | #print( "expected = ", expected ) | ||
+ | |||
+ | text = userText | ||
+ | if expected.count( "\n" ) != text.count( "\n" ): | ||
+ | print( "Function8 does not return the right number of lines." ) | ||
+ | print( "Function8 returns a string with", text.count( "\n" ), "lines, but" ) | ||
+ | print( "the right number should be", expected.count( "\n" ) + "." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | if type( expected ) != type( text ): | ||
+ | print( "Function8 does not return a string." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | noExpectedGremlins = expected.lower().count( "gremlin" ) | ||
+ | noReturnedGremlins = text.lower().count( "gremlin" ) | ||
+ | |||
+ | if ( noExpectedGremlins != noReturnedGremlins ): | ||
+ | print( "Function 8 returns", noReturnedGremlins, "while", | ||
+ | noExpectedGremlins, "are expected." ) | ||
+ | return int( 4.0*(noExpectedGremlins - | ||
+ | abs(noExpectedGremlins-noReturnedGremlins))/noExpectedGremlins), 4 | ||
+ | |||
+ | print( "Function 8 passes the tests. 4 out of 4." ) | ||
+ | return 4, 4 | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction9(): | ||
+ | try: | ||
+ | score, total = testFunction9b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function9 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | def testFunction9b(): | ||
+ | farm = [ "hen", "duck", "chicken", "mouse", "cat", "dog", "horse", "pig", "iguana", | ||
+ | "dragon", "unicorn" ] | ||
+ | # remove one animal at random | ||
+ | index = random.randrange( 1, len( farm )-2 ) | ||
+ | farm = farm[0:index] + farm[index+1: ] | ||
+ | |||
+ | expected = [ animal for i, animal in enumerate( farm ) if i%2==0 ] | ||
+ | userFarm = hw6.function9( farm ) | ||
+ | |||
+ | score = compare2Lists( "Function 9", userFarm, expected, "string" ) | ||
+ | |||
+ | if score == 1: | ||
+ | print( "Function 9 passes the tests. 4 out of 4." ) | ||
+ | return 4, 4 | ||
+ | else: | ||
+ | print( "Function 9 does not return the correct result. ", int(score*4), | ||
+ | "points out of 4." ) | ||
+ | return int( score*4 ), 4 | ||
+ | |||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction10(): | ||
+ | try: | ||
+ | score, total = testFunction10b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function10 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | def testFunction10b(): | ||
+ | temps = [ 31, 32, 33, 11, 40 ] | ||
+ | for temp in range( 15 ): | ||
+ | temps.append( random.choice( [100, 0, -5, -30, -32, 34 ] ) ) | ||
+ | |||
+ | expected = len( [ k for k in temps if k >= 32 ] ) | ||
+ | |||
+ | user = hw6.function10 ( temps ) | ||
+ | |||
+ | |||
+ | if user == expected: | ||
+ | print( "Function 10 passes the tests. 4 out of 4." ) | ||
+ | return 4, 4 | ||
+ | else: | ||
+ | print( "Function 10 returns", user, "but", | ||
+ | expected, "temperatures above 32 are in the list.", | ||
+ | " 0 points out of 4." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction11(): | ||
+ | try: | ||
+ | score, total = testFunction11b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function11 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | def testFunction11b(): | ||
+ | temps = [ 31, 32, 33, 11, 40 ] | ||
+ | for temp in range( 15 ): | ||
+ | temps.append( random.choice( [100, 0, -5, -30, -32, 34 ] ) ) | ||
+ | |||
+ | expected = [ k for k in temps if k >= 32 ] | ||
+ | |||
+ | user = hw6.function11 ( temps ) | ||
+ | |||
+ | score = compare2Lists( "Function 11", user, expected, "ints" ) | ||
+ | |||
+ | if score == 1: | ||
+ | print( "Function 11 passes the tests. 4 out of 4." ) | ||
+ | return 4, 4 | ||
+ | else: | ||
+ | print( "Function 11 does not return the correct result. ", int(score*4), | ||
+ | "points out of 4." ) | ||
+ | return int( score*4 ), 4 | ||
+ | |||
+ | |||
+ | # --------------------------------------------------------------------- | ||
+ | def testFunction12(): | ||
+ | try: | ||
+ | score, total = testFunction12b() | ||
+ | return score, total | ||
+ | except: | ||
+ | print( "Function12 does not exist or crashed. 0 out of 4 points." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | def testFunction12b(): | ||
+ | q = [ "Problematic", "Below average", "Average", "Very good", "Excellent", "Fail" ] | ||
+ | grades = [ 32, 100, 90, 74, 75, 60, 59, 61, 40, 11, 0 ] | ||
+ | expected = [ q[5], q[4], q[4], q[2], q[3], q[2], q[1], q[2], q[0], q[5], q[5] ] | ||
+ | |||
+ | noMatches = 0 | ||
+ | for i, grade in enumerate( grades ): | ||
+ | expectedString = expected[ i ] | ||
+ | userString = hw6.function12( grade ) | ||
+ | |||
+ | if type( expectedString ) != type( userString ): | ||
+ | print( "Function 12 does not return a string. 0 out of 4." ) | ||
+ | return 0, 4 | ||
+ | |||
+ | if expectedString != userString: | ||
+ | print( "Function 12 error: returns", userString, "for", grade, "instead of", | ||
+ | expectedString ) | ||
+ | else: | ||
+ | noMatches = noMatches + 1 | ||
+ | |||
+ | if noMatches != len( grades ): | ||
+ | print( "Function 12 passes", noMatches, "tests out of", len( grades ), end ="." ) | ||
+ | score = int( 4 * noMatches / len( grades ) ) | ||
+ | print( score, "out of 4." ) | ||
+ | return score, 4 | ||
+ | |||
+ | print( "Function 12 passes the tests. 4 out of 4." ) | ||
+ | return 4, 4 | ||
+ | |||
+ | |||
+ | def main(): | ||
+ | score = 0 | ||
+ | total = 0 | ||
+ | |||
+ | numberGood, maxGood = testFunction0() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction1() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction2() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction3() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction4() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction5() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction6() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction7() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction8() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction9() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction10() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction11() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | numberGood, maxGood = testFunction12() | ||
+ | score = score + numberGood | ||
+ | total = total + maxGood | ||
+ | |||
+ | print( "\nYour functions pass {0:1} tests out of {1:1}." | ||
+ | .format( score, total ) ) | ||
+ | |||
+ | |||
+ | main() | ||
+ | |||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | <br /> | ||
</onlydft> | </onlydft> | ||
<br /> | <br /> |
Latest revision as of 21:53, 10 March 2015
--D. Thiebaut (talk) 16:18, 1 March 2015 (EST)
<showafterdate after="20150305 16:00" before="20150601 00:00">
This assignment is due on 3/10/15 at 11:55 p.m.
Contents
Preparation
- Create a program called testHw6.py with the code available on this page. Save it in the same place where you will store your hw6.py program.
- Create a second program, called hw6.py. This program will contain all the functions that you are asked to write for this assignment. Add the code below to your hw6.py code:
# hw6.py # yourname here # This program contains functions that solve all the problems # of Homework 6, including a function0() that is given as a # bonus. # function0: receives a string, removes leading and trailing whitespace from # it, and capitalize all its words, and add two stars at both ends. Return the # new string. def function0( name ): name = "**" + name.strip().title() + "**" return name # ================================================ # M A I N # ================================================ def main(): # -------------------------------------------------------- # testing function0() with 3 different strings for name in [ "ARTHUR", " smith COLLEGE ", " lei " ]: newName = function0( name ) print( name ) print( newName ) print() if __name__=="__main__": main()
- The last 2 lines of the program are new. Don't worry about them, and just keep them in the code. All they do is call the main function when your program runs, the same way as before. The if __name__=="__main__": statement will be useful later. (You may want to read Section 7.1 in Zelle to learn more about this statement.)
- The hw6.py program contains 1 function called function0() that is passed a string as a parameter, and returns a new string. The new string is created by taking the parameter, removing leading and trailing whitespace characters, capitalizing all the words in it, and adding 2 stars at both ends.
- The main() function tests function0() by
- calling it and passing it as a parameter one of 3 different strings ("ARTHUR", " smith COLLEGE ", " lei "),
- catching the returned value in a variable called newName, and
- printing the parameter and the returned value.
- Run hw6.py and see how it works. Make sure you understand how main() tests function0().
- Switch to testHw6.py (which you can keep open in another Idle window) and run it.
- Here is the output you should get:
Function 0 passes 4 out of 4 tests. Function1 does not exist or crashed. 0 out of 4 points. Function2 does not exist or crashed. 0 out of 4 points. Function3 does not exist or crashed. 0 out of 3 points. Function4 does not exist or crashed. 0 out of 3 points. Function5 does not exist or crashed. 0 out of 3 points. Function6 does not exist or crashed. 0 out of 3 points. Function7 does not exist or crashed. 0 out of 3 points. Function8 does not exist or crashed. 0 out of 4 points. Function9 does not exist or crashed. 0 out of 4 points. Function10 does not exist or crashed. 0 out of 4 points. Function11 does not exist or crashed. 0 out of 4 points. Function12 does not exist or crashed. 0 out of 4 points. Your functions pass 4 tests out of 47.
- The output is telling you that function0() passed all 4 tests that testHw6.py subjected it to.
- testHw6.py also indicates that Function1, Function2, all the way to Function12 were not found. This is normal: your hw6.py program only contains only function0(). Your assignment for this week is to code 12 different functions. Let's get started!
As you can see, you will have 2 different ways to test your program: 1) by calling your functions with different parameters in the main() function of hw6.py, or 2) by running testHw6.py, which will automatically import your program and call its functions, one after the other, with different parameters.
Function 1
- Add a new function to your hw6.py program called function1(), with the following properties:
- it has 1 parameter that is an integer or float number that represents a temperature in Celsius.
- it returns the equivalent temperature in degrees Fahrenheit, defined as degree Fahrenheit = (degrees Celsius) * 9 / 5 + 32. The returned value is a float.
- Add a new section to the main() program of your hw6.py that calls function1( ) and passes it some known temperatures, and print the returned value. For example:
# test function1() with -31, 0, 10, and 20 degrees Celsius for celsius in [ -32, 0, 10, 20 ]: fahrenheit = function1( celsius ) print( "celsius =", celsius, " fahrenheit =", fahrenheit )
- When you are satisfied that your program works, run testHw6.py to verify that it, too, finds function1() to run correctly. testHw6.py will report on whether it can run your function, and whether it works correctly.
- If your function does not pass all the tests that testHw6.py subjects it to, you need to go back to hw6.py and see how you can modify function1().
Function 2
- Repeat the same steps you took for function1(), and this time add a new function called function2() to hw6.py with the following properties:
- function2() works the same way as function1() does, in that it receives a temperature in Celsius, and returns a temperature in Fahrenheit, but the returned value is the closest integer value in degree Fahrenheit.
Function 3
- Add a new function called function3() that receives a string as a parameter, and returns a new string.
- The parameter string contains a phone number, including an area code in parentheses.
- The returned string contains the phone number without the area code.
- For example, if the string passed to function3() is "(413) 555 1212", then the function returns "555 1212".
Function 4
- Add a new function called function4() to hw6.py with the following properties:
- It receives a string as a parameter. This string contains a phone number included in parentheses.
- The new function returns a new string that is similar to the string passed as a parameter, except that the area code of the phone number is replaced by "XXX"
- Example: function4( "Dial (413) 585 2700 for Smith College" ) will return the string "Dial (XXX) 585 2700 for Smith College".
Function 5
- Add a new function to hw6.py called function5().
- The parameter passed to function5 is a string containing a student Id number, of the form 990dddddd, where d is a digit.
- The function will anonymize the Id appearing in the string by replacing it with 990123456.
- Examples:
- function5( "My Id is 990111222. What is yours?" ) will return the string "My Id is 990123456. What is yours?".
- function5( "Alka's Id is 990998800." ) will return the string "Alka's Id is 990123456."
Function 6
- Add a new function called function6() that receives the name of a text file, and returns a string equal to the first line of the file.
- We assume that the file will always contain at least one line.
- Example: if the file named data.txt contains the text "Sophia Smith\nSmith College\nNorthampton\n", then calling function6( "data.txt" ) will return the string "Sophia Smith".
Function 7
- Add a new function called function7() that works in a very similar way function6() works, except now function7() will return the last line of the file whose name is passed as a parameter.
- We assume that the file will always contain at least one line.
- Example: if the file named text.dat contains the text "Sophia Smith\nSmith College\nNorthampton\n", then calling function7( "text.dat" ) will return the string "Northampton".
Function 8
- Add a new function called function8() that is passed the name of a text file. It returns the contents of the file a one long string where all the letters 'g' are replaced by "gremlin" and the letters 'G' by "Gremlin".
- Example: if the file named story.txt contains the string "Good job\nGreat god!\n", then calling function8( "story.txt" ) will make it return the string "Gremlinood job\nGremlinreat gremlinod!\n".
Function 9
- Open a new Idle window and create a new program with the code below:
def main(): farm = [ "dog", "cat", "mouse", "horse", "pig" ] newFarm = [] newFarm.append( farm[ 1 ] ) newFarm.append( farm[ 4 ] ) for i in range( len( newFarm ) ): print( newFarm[ i ] ) main()
- Observe the program. It has two lists. One contains several names of animals. The other one starts empty. The two brackets [] indicate that we are creating an empty list.
- Now, observe the output of the program. Notice how the program added two different elements of the original farm list to the empty list newFarm. The loop at the end goes through all the elements of newFarm and prints them. You will need to inspire yourself from this short program to write function9().
- Add a new function called function9() that receives as parameter a list of strings. It returns a new list made of all the items that are located at even indexes.
- Example: if the list farm is equal to [ "dog", "cat", "mouse", "horse", "pig" ], then calling function9( farm ) will make the function return the new list [ "dog", "mouse", "pig" ], because "dog" is at Index 0 in farm, "mouse" at Index 2, and "pig" at index 4.
Function 10
- Add a new function called function10() that receives as parameter a list of numbers. The numbers represent temperatures.
- The function returns an integer that is the number of temperatures in the list that are greater than or equal to 32.
- Example: if the variable temps is equal to [ 10, 40, 5, 32, 33 ], then function10( temps ) will return 3, since there are 3 temperatures of 32 or above in the list.
Function 11
- Add a new function called function11() that receives as parameter a list of numbers. The numbers represent temperatures here as well. The function returns a new list that contains only the temperatures that are 32 or above.
- Example: if the variable temps is equal to [ 10, 40, 5, 32, 33 ], then function11( temps ) will return the list [40, 32, 33], since these 3 temperatures are the only ones that are 32 or above in the first list.
Function 12
- Add a last function called function12() to your program. This function receives a number (integer or float) that represents a grade, ranging from 0 to 100, included. The function returns a string describing the grade.
- if the grade is 90 or above, function12() returns the string "Excellent"
- if the grade is 75 or above, but less than 90, function12() returns "Very good"
- if the grade is 60 or above, but less than 75, function12() returns "Average"
- if the grade is 50 or above, but less than 60, function12() returns "Below average"
- if the grade is 40 or above, but less than 50, function12() returns "Problematic"
- if the grade is lower than 40, function12() returns "Fail"
Moodle Submission
Submit just one program to Moodle, in the HW 6 PB 1 section.
</showafterdate>
<showafterdate after="20150313 00:00" before="20150601 00:00">
Solution Program
# hw6.py
# D. Thiebaut
# This program contains functions that solve all the problems
# of Homework 6, including a function0() that is given as a
# bonus.
def function0( name ):
name = "**" + name.strip().title() + "**"
return name
def function1( celsius ):
fahr = celsius * 9 / 5 + 32
return fahr
def function2( celsius ):
fahr = function1( celsius )
return int( round( fahr ) )
def function3( phoneString ):
phoneString = phoneString.strip()
index = phoneString.find( "(" )
return phoneString[ index+5: ].strip()
def function4( phoneString ):
index = phoneString.find( "(" )
beginningString = phoneString[0:index]
endString = phoneString[index+3+1+1: ]
return beginningString + "(XXX)" + endString
def function5( line ):
index = line.find( "990" )
beginningString = line[0:index]
endString = line[index+3+6: ]
return beginningString + "990123456" + endString
def function6( fileName ):
file = open( fileName, "r" )
lines = file.readlines()
file.close()
return lines[0].rstrip()
def function7( fileName ):
file = open( fileName, "r" )
lines = file.readlines()
file.close()
return lines[-1].rstrip()
def function8( fileName ):
file = open( fileName, "r" )
text = file.read()
file.close()
text = text.replace( "g", "gremlin" )
text = text.replace( "G", "Gremlin" )
return text
def function9( farm ):
newFarm = []
for i in range( 0, len( farm ), 2 ):
newFarm.append( farm[ i ] )
return newFarm
def function10( temps ):
count = 0
for temp in temps:
if temp >= 32:
count = count + 1
return count
def function11( temps ):
newTemps = []
for temp in temps:
if temp >= 32:
newTemps.append( temp )
return newTemps
def function12( grade ):
if ( grade >= 90 ): return "Excellent"
if ( grade >= 75 ): return "Very good"
if ( grade >= 60 ): return "Average"
if ( grade >= 50 ): return "Below average"
if ( grade >= 40 ): return "Problematic"
return "Fail"
def main():
# testing function0() with 3 different strings
for name in [ "ARTHUR", " smith COLLEGE ", " lei " ]:
newName = function0( name )
print( name )
print( newName )
print()
if __name__=="__main__":
main()
</showafterdate>