Difference between revisions of "CSC111 Lab 5 2015"

From dftwiki3
Jump to: navigation, search
 
(47 intermediate revisions by the same user not shown)
Line 2: Line 2:
 
----
 
----
  
<showafterdate after="20150225 11:00" before="20150601 00:00">
+
<br />
 
 
 
=Preparation=
 
=Preparation=
 
<br />
 
<br />
* Copy paste the program below in a new Idle window, and call it '''lab5Companion.py'''.  Save it to your working directory, where you normally save your lab programs.
+
* Copy paste the program below in a new Idle window, and call it '''lab5Companion.py'''.   
 +
* Save your new program to your working directory, where you normally save your lab programs.
 
* Run the program.  It should create 3 text files in your folder.  You will be using them in this lab.  The files are called:
 
* Run the program.  It should create 3 text files in your folder.  You will be using them in this lab.  The files are called:
 
**  chocoQuotes.txt
 
**  chocoQuotes.txt
Line 41: Line 41:
  
 
         # fetch the file and put its contents in the
 
         # fetch the file and put its contents in the
         # strign text.
+
         # string text.
 
         response = urllib.request.urlopen( url )
 
         response = urllib.request.urlopen( url )
 
         text    = response.read().decode( 'UTF-8' )
 
         text    = response.read().decode( 'UTF-8' )
Line 56: Line 56:
 
main()
 
main()
 
</source>
 
</source>
 +
<br />
 +
 +
<br />
 +
<showafterdate after="20150225 11:00" before="20150601 00:00">
 +
<br />
 +
<bluebox>
 +
Although this lab has only 2 Moodle submissions, make sure you work on '''all''' the challenges.  If you skip them, you are only making it harder for you to learn Python and making future challenges that much harder.  A little bit of effort regularly beats a huge effort later!  The Moodle submissions are due on 2/27 at 11:00 a.m. (morning, just before class).  Hope you enjoy this lab!
 +
</bluebox>
 +
<br />
 +
__TOC__
 
<br />
 
<br />
 
=Splitting Long Strings=
 
=Splitting Long Strings=
Line 72: Line 82:
 
Chocolate is the first luxury.
 
Chocolate is the first luxury.
 
It has so many things wrapped up in it:
 
It has so many things wrapped up in it:
Deliciusness in the moment,
+
Deliciousness in the moment,
 
childhood memories,
 
childhood memories,
 
and that grin-inducing
 
and that grin-inducing
Line 79: Line 89:
  
 
def main():
 
def main():
 +
    # make sure main knows that this variable exists
 +
    global text
 +
   
 
     # split the long string into individual lines
 
     # split the long string into individual lines
 
     lines = text.split( "\n" )
 
     lines = text.split( "\n" )
Line 90: Line 103:
 
<br />
 
<br />
 
* Run the program.  Verify that it outputs the entirety of the text.
 
* Run the program.  Verify that it outputs the entirety of the text.
* Just to make sure we understand what the variable '''lines''' contain, make your program print it, with a simple <tt>print( lines )</tt> statement.
+
* Just to make sure we understand what the variable '''lines''' contain, make your program print '''lines''', with a simple <tt>print( lines )</tt> statement.
* Observe that it's just a Python '''list'''.
+
* Observe that it's just a regular Python '''list'''.
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #1===
 +
|}
 +
[[Image:QuestionMark1.jpg|right|120px]]
 +
 
 +
* Modify your program, and make it print the poem so that each line is centered in a field of 60 spaces.  You must use the '''text''' variable, and print its line.  Do not create a new version of the poem!
 +
* Expected output
 +
<br />
 +
::<source lang="text">
 +
                        Chocolate                         
 +
              Chocolate is the first luxury.             
 +
          It has so many things wrapped up in it:         
 +
                Deliciousness in the moment,               
 +
                    childhood memories,                   
 +
                  and that grin-inducing                 
 +
        feeling of getting a reward for being good.       
 +
                    --Mariska Hargitay                   
 +
</source>
 +
<br />
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #2===
 +
|}
 +
[[Image:QuestionMark2.jpg|right|120px]]
 +
 
 +
* Make your program print the first line of the poem, centered, but also in uppercase.
 +
* Make it display the other lines centered, without changing their case.
 +
* Expected output
 +
<br />
 +
::<source lang="text">
 +
                        CHOCOLATE                         
 +
              Chocolate is the first luxury.             
 +
          It has so many things wrapped up in it:         
 +
                Deliciousness in the moment,               
 +
                    childhood memories,                   
 +
                  and that grin-inducing                 
 +
        feeling of getting a reward for being good.       
 +
                    --Mariska Hargitay                   
 +
</source>
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #3===
 +
|}
 +
[[Image:QuestionMark3.jpg|right|120px]]
 +
 
 +
* One more modification.  Now make your program print the last line right-justified in a field of 60 spaces.
 +
* The first line is still in upper-case.
 +
* Make it display the other lines centered, without changing their case.
 +
* Expected output
 +
<br />
 +
::<source lang="text">
 +
                        CHOCOLATE                         
 +
              Chocolate is the first luxury.             
 +
          It has so many things wrapped up in it:         
 +
                Deliciousness in the moment,               
 +
                    childhood memories,                   
 +
                  and that grin-inducing                 
 +
        feeling of getting a reward for being good.       
 +
                                          --Mariska Hargitay         
 +
</source>
 +
<br />
 +
 
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #4===
 +
|}
 +
[[Image:QuestionMark4.jpg|right|120px]]
 +
 
 +
* Make your program print the poem in a box.  The top and bottom lines have 50 dashes in them.
 +
* Expected output
 +
<br />
 +
::<source lang="text">
 +
+--------------------------------------------------+
 +
|                    CHOCOLATE                    |
 +
|          Chocolate is the first luxury.          |
 +
|    It has so many things wrapped up in it:      |
 +
|          Deliciousness in the moment,            |
 +
|              childhood memories,                |
 +
|              and that grin-inducing              |
 +
|  feeling of getting a reward for being good.    |
 +
|                                --Mariska Hargitay|
 +
+--------------------------------------------------+
 +
</source>
 +
<br />
 +
<br />
 +
=Reading Text From File=
 +
<br />
 +
* Open '''Finder''' or '''Windows Explorer''' and go to the folder that contains your '''lab5.py''' program, as well as your '''lab5Companion.py''' programs.  Make sure the folder contains the 3 text files you created earlier. 
 +
* Open the file name '''hargitay.txt'''.  Verify that it contains the same poem we have been playing with.
 +
* Either create a new program or add a new '''main()''' function to your existing program (rename the original main, '''main2()''', maybe?), and put the code below in the new function:
 +
<br />
 +
::<source lang="python">
 +
def main():
 +
    fileName = "hargitay.txt"
 +
    file = open( fileName, "r" )
 +
    lines = file.readlines()
 +
    file.close()
 +
 
 +
    for line in lines:
 +
        print( line )
 +
</source>
 +
* Run the program.  Observe its output.
 +
* The reason for the double-spacing is that each line read from the file contains a '\n' at the end of it.  And when you print such a line, the '''print()''' function adds its own \n at the end.    This is why you get a blank line in between lines.
 +
* One way to remove the '\n' at the end of each line is to print the line as follows: <tt>print( line.rstrip() )</tt>.  The '''rstrip()''' method right-strips the string of all ''white-space'' characters, which include spaces, tabs, and '\n'-characters.
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #5===
 +
|}
 +
[[Image:QuestionMark5.jpg|right|120px]]
 +
 
 +
* Make your program get the name of the file from the user, with an '''input()''' statement.
 +
* Then, make your program output the contents of the file in a box, as you did in Challenge 4.
 +
* Test your program by providing it with different file names:
 +
** hargitay.txt
 +
** joanneHarris.txt
 +
** chocoQuotes.txt
 +
* Adjust the width of the box if necessary.
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #6===
 +
|}
 +
[[Image:QuestionMark6.jpg|right|120px]]
 +
 
 +
* Exact same challenge as Challenge 5, but this time start with this program, where I have replaced the '''.readlines()''' method with '''.read()'''.
 +
<br />
 +
::<source lang="python">
 +
def main():
 +
    fileName = input( "File name? " )
 +
    file = open( fileName, "r" )
 +
    text = file.read()
 +
    file.close()
 +
 
 +
    print( "The type of text is", type( text ) )
 +
    print( "text = ", text )
 +
 
 +
 
 +
</source>
 +
<br />
 +
:; Note
 +
:: when Python says that something is of type <tt> <class 'str'></tt>, it means that it is a '''string'''.
 +
<br />
 +
<br />
 +
=Writing Text to File=
 +
<br />
 +
* Try this new version of main:
 +
<br />
 +
::<source lang="python">
 +
def main():
 +
    fileName = "hargitay.txt"
 +
    file = open( fileName, "r" )
 +
    text = file.read()
 +
    file.close()
 +
   
 +
    text = text.replace( "chocolate", "carrot" )
 +
    text = text.replace( "Chocolate", "Carrot" )
 +
 
 +
    file = open( fileName, "w" )
 +
    file.write( text + "\n" )
 +
    file.close()
 +
 
 +
</source>
 +
<br />
 +
* Open Finder or Windows Explorer, and take a look at the file "hargitay.txt", either with '''TextEdit''' or with '''Notepad'''.  See anything different?
 +
* BTW, You can recreate the original file by running the '''lab5Companion.py''' program again.
 +
<br />
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #7===
 +
|}
 +
[[Image:QuestionMark7.jpg|right|120px]]
 +
 
 +
* Modify the program so that it prompts the user for
 +
** The name of the file to read from and write to, and
 +
** a word
 +
: and make the program read the file, replace the word chocolate in it with the word the user picked, and save the resulting text back to the file.
 +
* Verify that your program works correctly, and that it modifies the file you select and replaces ''chocolate'' with the word you choose.
 +
<br />
 +
==Moodle Submission==
 +
<br />
 +
Rename your program '''lab5_7.py''', and submit your solution program for Challenge #7 to Moodle, in the Lab 5 PB 7 section.
 +
<br />
 +
=Functions=
 +
<br />
 +
==Preparation==
 +
<br />
 +
* Try the following statements in the Python console:
 +
<br />
 +
::<source lang="text">
 +
>>> def test():
 +
print( "hello" )
 +
print( "there" )
 +
 
 +
 +
>>> test()
 +
 
 +
 
 +
>>> def test():
 +
print( "hello", end="" )
 +
print( "there" )
 +
 
 +
 +
>>> test()
 +
 
 +
>>> def test():
 +
print( "hello", end="-" )
 +
print( "there" )
 +
 
 +
 +
>>> test()
 +
>>>
 +
</source>
 +
<br />
 +
Notice what happens when you add the <tt>end=""</tt> construct in the print statement.  It changes the way the print() function ends printing what it has to print.  By default, if you do not have an <tt>end=""</tt> construct, '''print()''' brings the cursor to the next line.  But this behavior can be changed.  We are going to use this, in the new program below.
 +
<br />
 +
==Functions and Stick Figure, Version 1==
 +
<br />
 +
* This section will be cleaner if you start a new program, rather than add to an existing program.
 +
* Add this code section to your new program:
 +
<br />
 +
::<source lang="python">
 +
def head():
 +
    print( "  o" )
 +
 
 +
def leftArm():
 +
    print( " /", end="" )
 +
 
 +
def torso():
 +
    print( "O", end="" )
 +
 
 +
def rightArm():
 +
    print( "\\" )
 +
 
 +
def leftLeg():
 +
    print( " /", end="" )
 +
 
 +
def rightLeg():
 +
    print( " \\" )
 +
 
 +
def stickFigure():
 +
    head()
 +
    leftArm()
 +
    torso()
 +
    rightArm()
 +
    leftLeg()
 +
    rightLeg()
 +
 
 +
def main():
 +
    stickFigure()
 +
 
 +
main()
 +
</source>
 +
<br />
 +
* Take a close look at the program.  Locate the <tt>end=""</tt> construct, which prevents the print from going to the next line when it's done. 
 +
* Notice also the "\\" string.  Because the '\' character is used to print special characters, like '\n' (new line), or '\t' (tab), if we want to print a regular backslash character, we have to use 2 backslashes next to each other.
 +
<br />
 +
* Run the program.  Notice how it displays a stick figure.
 +
<br />
 +
==Functions and Stick Figure, Version 2==
 +
<br />
 +
* Modify the stick figure program so that it looks like the code below:
 +
<br />
 +
::<source lang="python">
 +
def head():
 +
    print( "  o" )
 +
 
 +
def leftArm():
 +
    print( " /", end="" )
 +
 
 +
def torso():
 +
    print( "O", end="" )
 +
 
 +
def rightArm():
 +
    print( "\\" )
 +
 
 +
def leftLeg():
 +
    print( " /", end="" )
 +
 
 +
def rightLeg():
 +
    print( " \\" )
 +
 
 +
def body():
 +
    leftArm()
 +
    torso()
 +
    rightArm()
 +
 
 +
def newStickFigure():
 +
    head()
 +
    body()
 +
    leftLeg()
 +
    rightLeg()
 +
 
 +
def main():
 +
    newStickFigure()
 +
 
 +
main()
 +
</source>
 +
* Observe how the code is different, and the new function '''body()''' is used to display the body of the stick figure (torso plus arms).
 +
* Using the example of '''body()''', add a new function called '''legs()''' that will call '''leftLeg()''' and '''rightLeg()''' to draw both legs.  Modify newStickFigure() by removing the calls to '''leftLeg()''' and '''rightLeg()''', and adding instead a call to '''legs()'''.  Your new function should look something like this:
 +
<br />
 +
::<source lang="python">
 +
def newStickFigure():
 +
    head()
 +
    body()
 +
    legs()
 +
</source>
 +
<br />
 +
==Functions and Stick Figure, Version 3==
 +
<br />
 +
* Use the same approach to create this stick figure with a sword:
 +
<br />
 +
::<source lang="text">
 +
/+=====>
 +
\O___
 +
  |
 +
  |
 +
/ \
 +
/  \
 +
</source>
 +
<br />
 +
* Try to organize your functions similarly to the way I did.  Below is my stickFigure1() function.  Figure out the missing pieces!  Note: I added a '1' suffix to all the function names to differentiate them from the functions used for the other version of the stick-figure.
 +
<br />
 +
::<source lang="python">
 +
def stickFigure1():
 +
    leftForearm1()
 +
    sword1()
 +
    leftArm1()
 +
    head1()
 +
    rightArm1()
 +
    body1()
 +
    leftThigh1()
 +
    rightThigh1()
 +
    leftCalf1()
 +
    rightCalf1()
 +
</source>
 +
<br />
 +
=Happy Birthday!=
 +
<br />
 +
* Start with these three new functions:
 +
<br />
 +
::<source lang="python">
 +
def happyBirthday():
 +
    print( "Happy birthday to you!" )
 +
 
 +
def happyBirthdayDear( name ):
 +
    print( ("Happy birthday, dear " + name +"!" ) )
 +
 
 +
</source>
 +
<br />
 +
* Write a third function called '''singSong()''' that calls the two functions above.  When calling '''happyBirthdayDear( ... )''', pass it some name, say yours, or "Dave", or one of your friends.  You should get this kind of output:
 +
<br />
 +
::<source lang="text">
 +
Happy birthday to you!
 +
Happy birthday, dear Dave!
 +
</source>
 +
<br />
 +
* Modify '''singSong()''' so that it displays a more appropriate version on the song:
 +
<br />
 +
::<source lang="text">
 +
Happy birthday to you!
 +
Happy birthday to you!
 +
Happy birthday, dear Dave!
 +
Happy birthday to you!
 +
</source>
 +
<br />
 +
==Passing the Name as a Parameter==
 +
<br />
 +
* Modify your '''singSong( )''' function one more time.  I'm highlighting the lines that should change in your function:
 +
<br />
 +
::<source lang="python" highlight="1,4">
 +
def singSong( name ):
 +
    ...
 +
    ...
 +
    happyBirthdayDear( name )
 +
    ...
 +
</source>
 +
<br />
 +
* Now, make your program sing "Happy Birthday" to Dave, Karl, Jorge, and Tim!
 +
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #8===
 +
|}
 +
[[Image:QuestionMark8.jpg|right|120px]]
 +
 
 +
* Make your program prompt the user for a name in the '''main()''' function.
 +
* Then '''main()''' will pass the name to '''singSong()''', and your program will sing Happy Birthday to the person of your choice.
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
===Challenge #9===
 +
|}
 +
[[Image:QuestionMark9.jpg|right|120px]]
 +
<br />
 +
* Modify your solution program for Challenge 8 so that the user can enter several names on one line when prompted by your program.  Your program then "sings" happy birthday to all the friends, one after the other...
 +
<br />
 +
* Example:
 +
<br />
 +
::<source lang="text">
 +
Please enter the names of your friends: Jorge Karl Dave
 +
 
 +
Happy birthday to you!
 +
Happy birthday to you!
 +
Happy birthday, dear Jorge!
 +
Happy birthday to you!
 +
 
 +
Happy birthday to you!
 +
Happy birthday to you!
 +
Happy birthday, dear Karl!
 +
Happy birthday to you!
 +
 
 +
Happy birthday to you!
 +
Happy birthday to you!
 +
Happy birthday, dear Dave!
 +
Happy birthday to you!
 +
</source>
 +
<br />
 +
==Moodle Submission==
 +
<br />
 +
* Submit your solution program for Challenge 9 to Moodle, in Section LAB 5 PB 9.  You will need to rename your program lab5_9.py.
 +
<br />
 +
 
 +
</showafterdate>
 +
<br /><br />
 +
<showafterdate after="20150227 11:00" before="20150601 00:00">
 +
=Solution Programs=
 +
<br />
 +
::<source lang="python">
 +
# Solution program for Lab #5
 +
# All solutions to the challenges are stored in functions named challengex(),
 +
# where x is 1, 2, 3, etc.
 +
#
 +
 
 +
text = """Chocolate
 +
Chocolate is the first luxury.
 +
It has so many things wrapped up in it:
 +
Deliciousness in the moment,
 +
childhood memories,
 +
and that grin-inducing
 +
feeling of getting a reward for being good.
 +
--Mariska Hargitay"""
 +
 
 +
def makeTextFile():
 +
    file = open("hargitay.txt","w" )
 +
    file.write( text )
 +
    file.close()
 +
 
 +
 
 +
def bar():
 +
    print()
 +
    print( "-"*80 )
 +
 
 +
def program0():
 +
    # split the long string into individual lines
 +
    lines = text.split( "\n" )
 +
 
 +
    # print each line
 +
    for line in lines:
 +
        print( line )
 +
 
 +
def challenge1():
 +
    # split the long string into individual lines
 +
    lines = text.split( "\n" )
 +
 
 +
    # print each line
 +
    for line in lines:
 +
        print( line.center( 60 ) )
 +
 
 +
def challenge2():
 +
    # split the long string into individual lines
 +
    lines = text.split( "\n" )
 +
 
 +
    # print title
 +
    print( lines[0].upper().center( 60 ) )
 +
   
 +
    # print each line
 +
    for line in lines[1: ]:
 +
        print( line.center( 60 ) )
 +
 
 +
 
 +
def challenge3():
 +
    # split the long string into individual lines
 +
    lines = text.split( "\n" )
 +
 
 +
    # get first and last line
 +
    title = lines[0]
 +
    lastLine = lines[-1]
 +
 
 +
    # get first line and print it
 +
    print( title.upper().center( 60 ) )
 +
    print()
 +
   
 +
    # print poem, between title and last line
 +
    for line in lines[1:-1]:
 +
        print( line )
 +
 
 +
    # print last line right-justified
 +
    print( lastLine.rjust( 60 ) )
 +
 
 +
 
 +
def challenge4():
 +
    # split the long string into individual lines
 +
    lines = text.split( "\n" )
 +
 
 +
    bar = "+" + "-"*50 + "+"
 +
 
 +
    # get first line and print it
 +
    print( bar )
 +
    print( "|" + lines[0].upper().center( 50 ) + "|" )
 +
   
 +
    # print each line
 +
    for line in lines[1:-1]:
 +
        print( "|" + line.center(50) + "|" )
 +
    print( "|" + lines[-1].rjust(50) + "|" )
 +
    print( bar )
 +
 
 +
 
 +
def challenge5():
 +
    # open the file and read the lines in
 +
    fileName = "hargitay.txt"
 +
    file = open( fileName, "r" )
 +
    lines = file.readlines()
 +
    file.close()
 +
 
 +
    # create a bar for the top and bottom of box
 +
    bar = "+" + "-"*50 + "+"
 +
 
 +
    # get first line and print it
 +
    print( bar )
 +
    print( "|" + lines[0].upper().center( 50 ) + "|" )
 +
   
 +
    # print each line
 +
    for line in lines[1:-1]:
 +
        print( "|" + line.center(50) + "|" )
 +
    print( "|" + lines[-1].rjust(50) + "|" )
 +
    print( bar )
 +
 
 +
def challenge6():
 +
    # open the file and read the lines in
 +
    fileName = "hargitay.txt"
 +
    file = open( fileName, "r" )
 +
    text = file.read()
 +
    lines = text.split( "\n" )
 +
    file.close()
 +
 
 +
    # create a bar for the top and bottom of box
 +
    bar = "+" + "-"*50 + "+"
 +
 
 +
    # get first line and print it
 +
    print( bar )
 +
    print( "|" + lines[0].upper().center( 50 ) + "|" )
 +
   
 +
    # print each line
 +
    for line in lines[1:-1]:
 +
        print( "|" + line.center(50) + "|" )
 +
    print( "|" + lines[-1].rjust(50) + "|" )
 +
    print( bar )
 +
 
 +
 
 +
def challenge7():
 +
    # get the user input
 +
    fileName = input( "File name? " )
 +
    word    = input( "Word to swap in? " )
 +
   
 +
    # open the file and read the lines in
 +
    file = open( fileName, "r" )
 +
    text = file.read()
 +
    file.close()
 +
 
 +
    # replace chocolate by word before we split the text
 +
    text = text.replace( "Chocolate", word.capitalize() )
 +
    text = text.replace( "chocolate", word.lower() )
 +
    text = text.replace( "CHOCOLATE", word.upper() )
 +
 
 +
    file = open( fileName, "w" )
 +
    file.write( text )
 +
    file.close()
 +
 
 +
 
 +
 
 +
 
 +
# --------------------- stickFigure -----------------------
 +
 
 +
def head():
 +
    print( "  o" )
 +
 
 +
def leftArm():
 +
    print( " /", end="" )
 +
 
 +
def torso():
 +
    print( "O", end="" )
 +
 
 +
def rightArm():
 +
    print( "\\" )
 +
 
 +
def leftLeg():
 +
    print( " /", end="" )
 +
 
 +
def rightLeg():
 +
    print( " \\" )
 +
 
 +
def stickFigure():
 +
    head()
 +
    leftArm()
 +
    torso()
 +
    rightArm()
 +
    leftLeg()
 +
    rightLeg()
 +
 
 +
def body():
 +
    leftArm()
 +
    torso()
 +
    rightArm()
 +
 
 +
def legs():
 +
    leftLeg()
 +
    rightLeg()
 +
 
 +
def newStickFigure():
 +
    head()
 +
    body()
 +
    legs()
 +
 
 +
# --------------------- stickFigure1 ----------------------
 +
 
 +
def leftForearm1():
 +
    print( " /", end="" )
  
===
+
def sword1():
 +
    print( "+=====>" )
  
 +
def leftArm1():
 +
    print( " \\", end="" )
  
 +
def head1():
 +
    print( "O", end="" )
  
 +
def rightArm1():
 +
    print( "___" )
  
 +
def body1():
 +
    print( "  |" )
 +
    print( "  |" )
  
 +
def leftThigh1():
 +
    print( " / ", end="" )
 +
 +
def rightThigh1():
 +
    print( "\\" )
 +
 +
def leftCalf1():
 +
    print( "/  ", end ="" )
 +
 +
def rightCalf1():
 +
    print( "\\" )
 +
 +
def stickFigure1():
 +
    leftForearm1()
 +
    sword1()
 +
    leftArm1()
 +
    head1()
 +
    rightArm1()
 +
    body1()
 +
    leftThigh1()
 +
    rightThigh1()
 +
    leftCalf1()
 +
    rightCalf1()
 +
 +
 +
# ---------------------------------------------------------
 +
 +
 +
def happyBirthday():
 +
    print( "Happy birthday to you!" )
 +
 +
def happyBirthdayDear( name ):
 +
    print( "Happy birthday, dear " + name +"!"  )
 +
 +
def singSong( name ):
 +
    happyBirthday()
 +
    happyBirthday()
 +
    happyBirthdayDear( name )
 +
    happyBirthday()
 +
 +
 +
def challenge8( ):
 +
    # get the name from the user
 +
    name = input( "Who's birthday should we celebrate? " )
 +
 +
    # sing the song for that person
 +
    singSong( name )
 +
 +
# challenge 9
 +
def happyBirthday():
 +
    print( "Happy birthday to you!" )
 +
 +
def happyBirthdayDear( name ):
 +
    print( "Happy birthday, dear " + name +"!"  )
 +
 +
def singSong( name ):
 +
    happyBirthday()
 +
    happyBirthday()
 +
    happyBirthdayDear( name )
 +
    happyBirthday()
 +
 +
def challenge9( ):
 +
    # get a line of names, separated by spaces
 +
    line = input( "? " )
 +
 +
    # remove extra spaces at the front or back
 +
    line = line.strip()
 +
 +
    # split the line into individual names, and sing song for each
 +
    for name in line.split( " " ):
 +
        singSong( name )
 +
        # blank line separates the different songs
 +
        print()
 +
 +
 +
def bar():
 +
    print( "\n" + ( "-"*30 ) + "oOo" + ("-"*30 ) +"\n" )
 +
 +
   
 +
def main():
 +
   
 +
    challenge1()
 +
    bar()
 +
    challenge2()
 +
    bar()
 +
    challenge3()
 +
    bar()
 +
    challenge4()
 +
    bar()
 +
    challenge5()
 +
    bar()
 +
    challenge6()
 +
    bar()
 +
    challenge7()
 +
    bar()
 +
    challenge8()
 +
    bar()
 +
    challenge9()
 +
    bar()
 +
 
 +
   
 +
main()
 +
 +
 +
 +
</source>
 
</showafterdate>
 
</showafterdate>
 +
<br />
 +
<onlydft>
 +
=VPL Modules=
 +
<br />
 +
==Challenge 7==
 +
===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=lab5_7.py
 +
\$python \$prog
 +
 +
EOF
 +
 +
chmod +x vpl_execution
 +
</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
 +
 +
EOF
 +
 +
chmod +x vpl_execution
 +
 +
 +
</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
 +
 +
#--- define what the student program is called, and what the solution
 +
#--- program name is.
 +
module = "lab5_7"
 +
solutionModule = "lab5_7sol"
 +
userOutSplitPattern = "POEM"    # pattern used to start recording the user
 +
                              # output.  Useful when program does several
 +
                              # input() statements, and user output starts
 +
                              # after that.
 +
 +
 +
#--- GLOBALS ---
 +
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 ):
 +
    #--- generate random inputs ---
 +
    fileName = random.choice( [ "choco.txt", "choc.txt", "chocolat.txt" ] )
 +
   
 +
    title    = [ "POEM: Chocolate Poem", "POEM: Chocolate Chocolate", "POEM: Chocolate Anyone?" ]
 +
    lines    = [ "Chocolate, CHOCOLATE : you're the best!",
 +
                "Milk chocolate, dark chocolate?  Who cares?",
 +
                "I'm happy when I eat chocolate.  You?",
 +
                "This line does not contain c-h-o-c-o-l-a-t-e",
 +
                "It's cold... I want some hot chocolate, now!" ]
 +
    author  = [ "--Anonymous", "--Francis", "--DFT" ]
 +
    replace  = random.choice( [ "carrot", "cocoa", "cream" ] )
 +
 +
    poem    = [ random.choice( title ),
 +
                random.choice( lines ),
 +
                random.choice( lines ),
 +
                random.choice( lines ),
 +
                random.choice( author ) ]
 +
    poem = "\n".join( poem )
 +
 +
    #--- create data file with input data ---
 +
    text = poem + "\n"
 +
    file = open( fileName, "w" )
 +
    file.write( text )
 +
    file.close()
 +
 +
    #--- create input file for stdin ---
 +
    file = open( inputFileName, "w" )
 +
    file.write( fileName + "\n" )
 +
    file.write( replace + "\n" )
 +
    file.close()
 +
 +
    return  text
 +
 +
# 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!
 +
# ==================================================================
 +
 +
 +
 +
 +
# 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)
 +
 +
    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 )
 +
        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()
 +
    index = text.find( userOutSplitPattern ) #"+-" )
 +
    text = text[index:]
 +
    text = text.strip( ).strip( "\n" ) + "\n"
 +
    #print( text, end="" )
 +
    file.close()
 +
    return False, text
 +
 +
def removeBlankLines( lines ):
 +
    newLines = []
 +
    for line in lines.split( "\n" ):
 +
        if len( line )==0:
 +
            continue
 +
        newLines.append( line )
 +
 +
    return ( "\n".join( newLines ) ) + "\n"
 +
 +
def compareUserExpected( inputLines, userOutText, expectedOutText ):
 +
    userOutText = removeBlankLines( userOutText )
 +
    expectedOutText = removeBlankLines( expectedOutText )
 +
    #print( "userOutText:" + userOutText )
 +
    #print( "expectedOutText:" + expectedOutText )
 +
    misMatchLineNumbers = []
 +
    userTextOutLines = userOutText.split( "\n" )
 +
    expectedOutTextLines = expectedOutText.split( "\n" )
 +
 +
    for i in range( len( userTextOutLines ) ):
 +
        lineNo = i+1
 +
        if userTextOutLines[i] != expectedOutTextLines[i]:
 +
            misMatchLineNumbers.append( lineNo )
 +
   
 +
    return misMatchLineNumbers
 +
           
 +
 +
 +
def main():
 +
    global module
 +
    global solutionModule
 +
 +
   
 +
    #--- 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"
 +
                    + "Your program was tested with:\n"
 +
                    + inputLines  + "\n"
 +
                    + "Error message:\n"
 +
                    + errorMessage + "\n" )
 +
        printGrade( 50 )
 +
        return
 +
 +
                   
 +
    error, userOutText        = runModule( module, "input", "userOut" )
 +
    if error:
 +
        commentLong( "- Your program crashed...\n"
 +
                    + "Your program was tested with:\n"
 +
                    + inputLines  + "\n"
 +
                    + "Error message:\n"
 +
                    + userOutText + "\n" )
 +
        printGrade( 50 )
 +
        return
 +
 +
    dummy, expectedOutText    = runModule( solutionModule, "input", "expectedOut" )
 +
 +
    misMatchLineNumbers = compareUserExpected( inputLines,
 +
                                              userOutText,
 +
                                              expectedOutText )
 +
    if len( misMatchLineNumbers ) == 0:
 +
        commentLong( "- Congrats, correct output!\n"
 +
                    +"Your program was tested with:\n"
 +
                    +inputLines + "\n"
 +
                    +"Your output:\n"
 +
                    +userOutText + "\n" )
 +
        printGrade( 100 )
 +
    else:
 +
        s = "" if len( misMatchLineNumbers ) == 1 else "s"
 +
 +
        commentLong( "-Incorrect output.\n"
 +
                    +"Your program was tested with:\n"
 +
                    +inputLines + "\n"
 +
                    +"Your output:\n"
 +
                    +userOutText + "\n"
 +
                    +"Expected output:\n"
 +
                    +expectedOutText + "\n"
 +
                    +("There are mismatches in Line%s " % s) +
 +
                    ", ".join( [str(k) for k in misMatchLineNumbers] )
 +
                    +"\n" )
 +
        noLinesGood = len( expectedOutText.strip().split("\n") )
 +
        noErrors    = len( misMatchLineNumbers )
 +
        #print( "noLinesGood = ", noLinesGood, " noErrors = ", noErrors )
 +
 +
        grade      = round( 60 + 40 / noLinesGood *( noLinesGood- noErrors ) )
 +
        printGrade( grade )
 +
 +
main()
 +
 +
 +
 +
</source>
 +
<br />
 +
 +
==Challenge 9==
 +
 +
===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
 +
 +
#--- define what the student program is called, and what the solution
 +
#--- program name is.
 +
module = "lab5_9"
 +
solutionModule = module + "sol"
 +
userOutSplitPattern = "Ha"    # 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
 +
 +
#--- GLOBALS ---
 +
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 ):
 +
    #--- generate random inputs ---
 +
 +
    list = []
 +
    for i in range( random.choice( [2, 5, 3] ) ):
 +
        list.append( random.choice( [ "Dave", "Jorge", "Max", "Carl", "Tim" ] ) )
 +
   
 +
    names = " ".join( list )
 +
 +
    #--- create input file for stdin ---
 +
    file = open( inputFileName, "w" )
 +
    file.write( names + "\n" )
 +
    file.close()
 +
 +
    return names + "\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!
 +
# ==================================================================
 +
 +
 +
 +
 +
# 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 )
 +
        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()
 +
    index = text.find( userOutSplitPattern ) #"+-" )
 +
    text = text[index:]
 +
    text = text.strip( ).strip( "\n" ) + "\n"
 +
    #print( text, end="" )
 +
    file.close()
 +
    return False, text
 +
 +
def removeBlankLines( lines ):
 +
    newLines = []
 +
    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
 +
 +
    userOutText = removeBlankLines( userOutText )
 +
    expectedOutText = removeBlankLines( expectedOutText )
 +
    misMatchLineNumbers = []
 +
    userTextOutLines = userOutText.split( "\n" )
 +
    expectedOutTextLines = expectedOutText.split( "\n" )
 +
 +
    for i in range( len( userTextOutLines ) ):
 +
        lineNo = i+1
 +
        userLine = userTextOutLines[i]
 +
        expectedLine = expectedOutTextLines[i]
 +
        if stripOutputsBeforeCompare:
 +
            userLine = userLine.strip()
 +
            expectedLine = expectedLine.strip()
 +
        if userLine != expectedLine:
 +
            #print( "user    >" + userTextOutLines[i] + "<" )
 +
            #print( "expected >" + expectedOutTextLines[i] + "<" )
 +
            misMatchLineNumbers.append( lineNo )
 +
   
 +
    return misMatchLineNumbers
 +
           
 +
 +
 +
def main():
 +
    global module
 +
    global solutionModule
 +
 +
   
 +
    #--- 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"
 +
                    + "Your program was tested with:\n"
 +
                    + inputLines  + "\n"
 +
                    + "Error message:\n"
 +
                    + errorMessage + "\n" )
 +
        printGrade( 50 )
 +
        return
 +
 +
                   
 +
    error, userOutText        = runModule( module, "input", "userOut" )
 +
    if error:
 +
        commentLong( "- Your program crashed...\n"
 +
                    + "Your program was tested with:\n"
 +
                    + inputLines  + "\n"
 +
                    + "Error message:\n"
 +
                    + userOutText + "\n" )
 +
        printGrade( 50 )
 +
        return
 +
 +
    dummy, expectedOutText    = runModule( solutionModule, "input", "expectedOut" )
 +
 +
    misMatchLineNumbers = compareUserExpected( inputLines,
 +
                                              userOutText,
 +
                                              expectedOutText )
 +
    if len( misMatchLineNumbers ) == 0:
 +
        commentLong( "- Congrats, correct output!\n"
 +
                    +"Your program was tested with:\n"
 +
                    +inputLines + "\n"
 +
                    +"Your output:\n"
 +
                    +userOutText + "\n" )
 +
        printGrade( 100 )
 +
    else:
 +
        s = "" if len( misMatchLineNumbers ) == 1 else "s"
 +
 +
        commentLong( "-Incorrect output.\n"
 +
                    +"Your program was tested with:\n"
 +
                    +inputLines + "\n"
 +
                    +"Your output:\n"
 +
                    +userOutText + "\n"
 +
                    +"Expected output:\n"
 +
                    +expectedOutText + "\n"
 +
                    +("There are errors in Line%s " % s) +
 +
                    ", ".join( [str(k) for k in misMatchLineNumbers] )
 +
                    +"\n" )
 +
        noLinesGood = len( expectedOutText.strip().split("\n") )
 +
        noErrors    = len( misMatchLineNumbers )
 +
        #print( "noLinesGood = ", noLinesGood, " noErrors = ", noErrors )
 +
 +
        grade      = round( 60 + 40 / noLinesGood *( noLinesGood- noErrors ) )
 +
        printGrade( grade )
 +
 +
main()
 +
 +
 +
 +
 +
</source>
 +
<br />
 +
</onlydft>
 +
<br /><br /><br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
[[Category:CSC111]][[Category:Labs]][[Category:Python]]

Latest revision as of 16:05, 13 June 2015

--D. Thiebaut (talk) 12:17, 22 February 2015 (EST)



Preparation


  • Copy paste the program below in a new Idle window, and call it lab5Companion.py.
  • Save your new program to your working directory, where you normally save your lab programs.
  • Run the program. It should create 3 text files in your folder. You will be using them in this lab. The files are called:
    • chocoQuotes.txt
    • hargitay.txt
    • joanneHarris.txt


# lab5Companion.py
# D. Thiebaut
# This program will create several files in the directory
# where you will run it.
# The files are retrieved from a Web server, stored temporarily
# in a string, and stored in a local file on your disk.
# The 3 files are very, very short.
# Their names are:
# - chocoQuotes.txt
# - hargitay.txt
# - joanneHarris.txt

import urllib.request  # the lib that handles the url stuff

# main program
def main():

    # list of files to retrieve 
    fileNames = [ "chocoQuotes.txt", "hargitay.txt", "joanneHarris.txt" ]

    # get each file, one at a time
    for fileName in fileNames:

        # url where the files are located
        url = "http://cs.smith.edu/~dthiebaut/111/files/" + fileName

        # fetch the file and put its contents in the
        # string text.
        response = urllib.request.urlopen( url )
        text     = response.read().decode( 'UTF-8' )
        
        # write text to file, in the same directory as this program.
        file     = open( fileName, "w" )
        file.write( text + "\n" )
        file.close()

        # give feedback to user.
        print( "File {0:1} created in your folder".format( fileName ) )


main()



<showafterdate after="20150225 11:00" before="20150601 00:00">

Although this lab has only 2 Moodle submissions, make sure you work on all the challenges. If you skip them, you are only making it harder for you to learn Python and making future challenges that much harder. A little bit of effort regularly beats a huge effort later! The Moodle submissions are due on 2/27 at 11:00 a.m. (morning, just before class). Hope you enjoy this lab!



Splitting Long Strings


In this section you will see how to take text represented as a multi-line string, and process it various ways.


  • Long strings that span several lines can be created by enclosing them in triple quotes; either triple single-quotes (), or triple double-quotes (""").
  • Copy/paste the program below in a new program. You may call it lab5.py


# lab5.py

text = """Chocolate
Chocolate is the first luxury.
It has so many things wrapped up in it:
Deliciousness in the moment,
childhood memories,
and that grin-inducing
feeling of getting a reward for being good.
--Mariska Hargitay"""

def main():
    # make sure main knows that this variable exists
    global text
    
    # split the long string into individual lines
    lines = text.split( "\n" )

    # print each line
    for line in lines:
        print( line )

main()


  • Run the program. Verify that it outputs the entirety of the text.
  • Just to make sure we understand what the variable lines contain, make your program print lines, with a simple print( lines ) statement.
  • Observe that it's just a regular Python list.



Challenge #1

QuestionMark1.jpg
  • Modify your program, and make it print the poem so that each line is centered in a field of 60 spaces. You must use the text variable, and print its line. Do not create a new version of the poem!
  • Expected output


                         Chocolate                          
               Chocolate is the first luxury.               
          It has so many things wrapped up in it:           
                Deliciousness in the moment,                 
                    childhood memories,                     
                   and that grin-inducing                   
        feeling of getting a reward for being good.         
                     --Mariska Hargitay




Challenge #2

QuestionMark2.jpg
  • Make your program print the first line of the poem, centered, but also in uppercase.
  • Make it display the other lines centered, without changing their case.
  • Expected output


                         CHOCOLATE                          
               Chocolate is the first luxury.               
          It has so many things wrapped up in it:           
                Deliciousness in the moment,                 
                    childhood memories,                     
                   and that grin-inducing                   
        feeling of getting a reward for being good.         
                     --Mariska Hargitay



Challenge #3

QuestionMark3.jpg
  • One more modification. Now make your program print the last line right-justified in a field of 60 spaces.
  • The first line is still in upper-case.
  • Make it display the other lines centered, without changing their case.
  • Expected output


                         CHOCOLATE                          
               Chocolate is the first luxury.               
          It has so many things wrapped up in it:           
                Deliciousness in the moment,                 
                    childhood memories,                     
                   and that grin-inducing                   
        feeling of getting a reward for being good.         
                                          --Mariska Hargitay



Challenge #4

QuestionMark4.jpg
  • Make your program print the poem in a box. The top and bottom lines have 50 dashes in them.
  • Expected output


+--------------------------------------------------+
|                    CHOCOLATE                     |
|          Chocolate is the first luxury.          |
|     It has so many things wrapped up in it:      |
|           Deliciousness in the moment,            |
|               childhood memories,                |
|              and that grin-inducing              |
|   feeling of getting a reward for being good.    |
|                                --Mariska Hargitay|
+--------------------------------------------------+



Reading Text From File


  • Open Finder or Windows Explorer and go to the folder that contains your lab5.py program, as well as your lab5Companion.py programs. Make sure the folder contains the 3 text files you created earlier.
  • Open the file name hargitay.txt. Verify that it contains the same poem we have been playing with.
  • Either create a new program or add a new main() function to your existing program (rename the original main, main2(), maybe?), and put the code below in the new function:


def main():
    fileName = "hargitay.txt"
    file = open( fileName, "r" )
    lines = file.readlines()
    file.close()

    for line in lines:
        print( line )
  • Run the program. Observe its output.
  • The reason for the double-spacing is that each line read from the file contains a '\n' at the end of it. And when you print such a line, the print() function adds its own \n at the end. This is why you get a blank line in between lines.
  • One way to remove the '\n' at the end of each line is to print the line as follows: print( line.rstrip() ). The rstrip() method right-strips the string of all white-space characters, which include spaces, tabs, and '\n'-characters.



Challenge #5

QuestionMark5.jpg
  • Make your program get the name of the file from the user, with an input() statement.
  • Then, make your program output the contents of the file in a box, as you did in Challenge 4.
  • Test your program by providing it with different file names:
    • hargitay.txt
    • joanneHarris.txt
    • chocoQuotes.txt
  • Adjust the width of the box if necessary.



Challenge #6

QuestionMark6.jpg
  • Exact same challenge as Challenge 5, but this time start with this program, where I have replaced the .readlines() method with .read().


def main():
    fileName = input( "File name? " )
    file = open( fileName, "r" )
    text = file.read()
    file.close()

    print( "The type of text is", type( text ) )
    print( "text = ", text )


Note
when Python says that something is of type <class 'str'>, it means that it is a string.



Writing Text to File


  • Try this new version of main:


def main():
    fileName = "hargitay.txt"
    file = open( fileName, "r" )
    text = file.read()
    file.close()
    
    text = text.replace( "chocolate", "carrot" )
    text = text.replace( "Chocolate", "Carrot" )

    file = open( fileName, "w" )
    file.write( text + "\n" )
    file.close()


  • Open Finder or Windows Explorer, and take a look at the file "hargitay.txt", either with TextEdit or with Notepad. See anything different?
  • BTW, You can recreate the original file by running the lab5Companion.py program again.




Challenge #7

QuestionMark7.jpg
  • Modify the program so that it prompts the user for
    • The name of the file to read from and write to, and
    • a word
and make the program read the file, replace the word chocolate in it with the word the user picked, and save the resulting text back to the file.
  • Verify that your program works correctly, and that it modifies the file you select and replaces chocolate with the word you choose.


Moodle Submission


Rename your program lab5_7.py, and submit your solution program for Challenge #7 to Moodle, in the Lab 5 PB 7 section.

Functions


Preparation


  • Try the following statements in the Python console:


>>> def test():
	print( "hello" )
	print( "there" )

	
>>> test()


>>> def test():
	print( "hello", end="" )
	print( "there" )

	
>>> test()

>>> def test():
	print( "hello", end="-" )
	print( "there" )

	
>>> test()
>>>


Notice what happens when you add the end="" construct in the print statement. It changes the way the print() function ends printing what it has to print. By default, if you do not have an end="" construct, print() brings the cursor to the next line. But this behavior can be changed. We are going to use this, in the new program below.

Functions and Stick Figure, Version 1


  • This section will be cleaner if you start a new program, rather than add to an existing program.
  • Add this code section to your new program:


def head():
    print( "  o" )

def leftArm():
    print( " /", end="" )

def torso():
    print( "O", end="" )

def rightArm():
    print( "\\" )

def leftLeg():
    print( " /", end="" )

def rightLeg():
    print( " \\" )

def stickFigure():
    head()
    leftArm()
    torso()
    rightArm()
    leftLeg()
    rightLeg()

def main():
    stickFigure()

main()


  • Take a close look at the program. Locate the end="" construct, which prevents the print from going to the next line when it's done.
  • Notice also the "\\" string. Because the '\' character is used to print special characters, like '\n' (new line), or '\t' (tab), if we want to print a regular backslash character, we have to use 2 backslashes next to each other.


  • Run the program. Notice how it displays a stick figure.


Functions and Stick Figure, Version 2


  • Modify the stick figure program so that it looks like the code below:


def head():
    print( "  o" )

def leftArm():
    print( " /", end="" )

def torso():
    print( "O", end="" )

def rightArm():
    print( "\\" )

def leftLeg():
    print( " /", end="" )

def rightLeg():
    print( " \\" )

def body():
    leftArm()
    torso()
    rightArm()

def newStickFigure():
    head()
    body()
    leftLeg()
    rightLeg()

def main():
    newStickFigure()

main()
  • Observe how the code is different, and the new function body() is used to display the body of the stick figure (torso plus arms).
  • Using the example of body(), add a new function called legs() that will call leftLeg() and rightLeg() to draw both legs. Modify newStickFigure() by removing the calls to leftLeg() and rightLeg(), and adding instead a call to legs(). Your new function should look something like this:


def newStickFigure():
    head()
    body()
    legs()


Functions and Stick Figure, Version 3


  • Use the same approach to create this stick figure with a sword:


 /+=====>
 \O___
  |
  |
 / \
/   \


  • Try to organize your functions similarly to the way I did. Below is my stickFigure1() function. Figure out the missing pieces! Note: I added a '1' suffix to all the function names to differentiate them from the functions used for the other version of the stick-figure.


def stickFigure1():
    leftForearm1()
    sword1()
    leftArm1()
    head1()
    rightArm1()
    body1()
    leftThigh1()
    rightThigh1()
    leftCalf1()
    rightCalf1()


Happy Birthday!


  • Start with these three new functions:


def happyBirthday():
    print( "Happy birthday to you!" )

def happyBirthdayDear( name ):
    print( ("Happy birthday, dear " + name +"!" ) )


  • Write a third function called singSong() that calls the two functions above. When calling happyBirthdayDear( ... ), pass it some name, say yours, or "Dave", or one of your friends. You should get this kind of output:


Happy birthday to you!
Happy birthday, dear Dave!


  • Modify singSong() so that it displays a more appropriate version on the song:


Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Dave!
Happy birthday to you!


Passing the Name as a Parameter


  • Modify your singSong( ) function one more time. I'm highlighting the lines that should change in your function:


def singSong( name ):
     ...
     ...
     happyBirthdayDear( name )
     ...


  • Now, make your program sing "Happy Birthday" to Dave, Karl, Jorge, and Tim!


Challenge #8

QuestionMark8.jpg
  • Make your program prompt the user for a name in the main() function.
  • Then main() will pass the name to singSong(), and your program will sing Happy Birthday to the person of your choice.






Challenge #9

QuestionMark9.jpg


  • Modify your solution program for Challenge 8 so that the user can enter several names on one line when prompted by your program. Your program then "sings" happy birthday to all the friends, one after the other...


  • Example:


Please enter the names of your friends: Jorge Karl Dave

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Jorge!
Happy birthday to you!

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Karl!
Happy birthday to you!

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Dave!
Happy birthday to you!


Moodle Submission


  • Submit your solution program for Challenge 9 to Moodle, in Section LAB 5 PB 9. You will need to rename your program lab5_9.py.


</showafterdate>

<showafterdate after="20150227 11:00" before="20150601 00:00">

Solution Programs


# Solution program for Lab #5
# All solutions to the challenges are stored in functions named challengex(),
# where x is 1, 2, 3, etc.
#

text = """Chocolate
Chocolate is the first luxury.
It has so many things wrapped up in it:
Deliciousness in the moment,
childhood memories,
and that grin-inducing
feeling of getting a reward for being good.
--Mariska Hargitay"""

def makeTextFile():
    file = open("hargitay.txt","w" )
    file.write( text )
    file.close()


def bar():
    print()
    print( "-"*80 )

def program0():
    # split the long string into individual lines
    lines = text.split( "\n" )

    # print each line
    for line in lines:
        print( line )

def challenge1():
    # split the long string into individual lines
    lines = text.split( "\n" )

    # print each line
    for line in lines:
        print( line.center( 60 ) )

def challenge2():
    # split the long string into individual lines
    lines = text.split( "\n" )

    # print title
    print( lines[0].upper().center( 60 ) )
    
    # print each line
    for line in lines[1: ]:
        print( line.center( 60 ) )


def challenge3():
    # split the long string into individual lines
    lines = text.split( "\n" )

    # get first and last line
    title = lines[0]
    lastLine = lines[-1]

    # get first line and print it
    print( title.upper().center( 60 ) )
    print()
    
    # print poem, between title and last line
    for line in lines[1:-1]:
        print( line )

    # print last line right-justified
    print( lastLine.rjust( 60 ) )


def challenge4():
    # split the long string into individual lines
    lines = text.split( "\n" )

    bar = "+" + "-"*50 + "+"

    # get first line and print it
    print( bar )
    print( "|" + lines[0].upper().center( 50 ) + "|" )
    
    # print each line
    for line in lines[1:-1]:
        print( "|" + line.center(50) + "|" )
    print( "|" + lines[-1].rjust(50) + "|" )
    print( bar )


def challenge5():
    # open the file and read the lines in
    fileName = "hargitay.txt"
    file = open( fileName, "r" )
    lines = file.readlines()
    file.close()

    # create a bar for the top and bottom of box
    bar = "+" + "-"*50 + "+"

    # get first line and print it
    print( bar )
    print( "|" + lines[0].upper().center( 50 ) + "|" )
    
    # print each line
    for line in lines[1:-1]:
        print( "|" + line.center(50) + "|" )
    print( "|" + lines[-1].rjust(50) + "|" )
    print( bar )

def challenge6():
    # open the file and read the lines in
    fileName = "hargitay.txt"
    file = open( fileName, "r" )
    text = file.read()
    lines = text.split( "\n" )
    file.close()

    # create a bar for the top and bottom of box
    bar = "+" + "-"*50 + "+"

    # get first line and print it
    print( bar )
    print( "|" + lines[0].upper().center( 50 ) + "|" )
    
    # print each line
    for line in lines[1:-1]:
        print( "|" + line.center(50) + "|" )
    print( "|" + lines[-1].rjust(50) + "|" )
    print( bar )


def challenge7():
    # get the user input
    fileName = input( "File name? " )
    word     = input( "Word to swap in? " )
    
    # open the file and read the lines in
    file = open( fileName, "r" )
    text = file.read()
    file.close()

    # replace chocolate by word before we split the text
    text = text.replace( "Chocolate", word.capitalize() )
    text = text.replace( "chocolate", word.lower() )
    text = text.replace( "CHOCOLATE", word.upper() )

    file = open( fileName, "w" )
    file.write( text )
    file.close()

  


# --------------------- stickFigure -----------------------

def head():
    print( "  o" )

def leftArm():
    print( " /", end="" )

def torso():
    print( "O", end="" )

def rightArm():
    print( "\\" )

def leftLeg():
    print( " /", end="" )

def rightLeg():
    print( " \\" )

def stickFigure():
    head()
    leftArm()
    torso()
    rightArm()
    leftLeg()
    rightLeg()

def body():
    leftArm()
    torso()
    rightArm()

def legs():
    leftLeg()
    rightLeg()

def newStickFigure():
    head()
    body()
    legs()

# --------------------- stickFigure1 ----------------------

def leftForearm1():
    print( " /", end="" )

def sword1():
    print( "+=====>" )

def leftArm1():
    print( " \\", end="" )

def head1():
    print( "O", end="" )

def rightArm1():
    print( "___" )

def body1():
    print( "  |" )
    print( "  |" )

def leftThigh1():
    print( " / ", end="" )

def rightThigh1():
    print( "\\" )

def leftCalf1():
    print( "/   ", end ="" )

def rightCalf1():
    print( "\\" )

def stickFigure1():
    leftForearm1()
    sword1()
    leftArm1()
    head1()
    rightArm1()
    body1()
    leftThigh1()
    rightThigh1()
    leftCalf1()
    rightCalf1()


# ---------------------------------------------------------


def happyBirthday():
    print( "Happy birthday to you!" )

def happyBirthdayDear( name ):
    print( "Happy birthday, dear " + name +"!"  )

def singSong( name ):
    happyBirthday()
    happyBirthday()
    happyBirthdayDear( name )
    happyBirthday()


def challenge8( ):
    # get the name from the user
    name = input( "Who's birthday should we celebrate? " )

    # sing the song for that person
    singSong( name )

# challenge 9
def happyBirthday():
    print( "Happy birthday to you!" )

def happyBirthdayDear( name ):
    print( "Happy birthday, dear " + name +"!"  )

def singSong( name ):
    happyBirthday()
    happyBirthday()
    happyBirthdayDear( name )
    happyBirthday()

def challenge9( ):
    # get a line of names, separated by spaces
    line = input( "? " )

    # remove extra spaces at the front or back
    line = line.strip()

    # split the line into individual names, and sing song for each
    for name in line.split( " " ):
        singSong( name )
        # blank line separates the different songs
        print()


def bar():
    print( "\n" + ( "-"*30 ) + "oOo" + ("-"*30 ) +"\n" )

    
def main():
    
    challenge1()
    bar()
    challenge2()
    bar()
    challenge3()
    bar()
    challenge4()
    bar()
    challenge5()
    bar()
    challenge6()
    bar()
    challenge7()
    bar()
    challenge8()
    bar()
    challenge9()
    bar()
  
    
main()

</showafterdate>


...