CSC 111: Introduction to Computer Science

HW 3: Data Types, Math, Date and Random Libraries Feedback and Solutions

Part 1: Fibonacci Sequence

Commenting

Code Clarity
At all times, you want your computer program to exhibit clear and logical thinking. If you have unused lines of code, cut them out, or at a minimum, comment them out AND include an additional comment explaining, for example, that the next lines are for debugging.

Also be sure to close your program gracefully, which for now means you must include the .getMouse() and .close() methods at the end of your programs.

'for' Loop Structure
The portion of your algorithm that is repeated is crying out to be inside a 'for' loop. The entire 'for' loop structure though can be thought of as including the variable initialization that occurs before entering the loop, and any final calculations or output that happens after exiting the 'for' loop. As in the feedback from HW2, you need to be carefull about "arranging the ideal order of computation." This includes what happens before entering the 'for' loop, the order of your statements inside the loop, and what happens after the loop. One way to structure the loop for the Fibonacci sequence is:

One Possible Solution

# HW3_Fib.py
#
# J Cardell, Feb 16, 2011
#
# HW3 part 1: Calculate and graph the Fibonacci sequence

from graphics import *

def main():
    n = input("Enter a number: ")

    # Initialize variables to start the Fibonacci sequence
    # We need two variables, since the definition of the sequence
    # is to add the previous two numbers in the sequence
    x = 0
    y = 1
    print "First Fib num = ", x
    print "Second Fib num = ", y

    # Set up the graphing window, and graph first two values in the sequence
    win = GraphWin("Fibonacci", 1000, 1000)
    win.setBackground('cyan')
    # Scale the x-axis to span 0 to n, plus a small margin
    xScale = n + 2

    # To scale the y-axis: we need to know the end of the sequence, so find
    # the sequence initially, in order to set up the y-axis coordinates
    # This is a brute force method - any code that has SOMETHING interesting
    # for graphing is a good solution for this HW. The purpose here is to
    # motivate concepts coming later in the semester - arrays, nested loops ...
    # A number of you also used the closed for solution, which is a great
    # approach, and more elegant than this one.
    for w in range(1, n-1):
        # See comments in identical loop below
        x, y = y, x
        y = y + x
    yScale = y + n
    win.setCoords(0, 0, xScale, yScale)

    # Since the first two values were given new values, in the 'for' loop
    # above, they must be reinitialized for initial graphing and for the
    # next 'for' loop
    x = 0
    y = 1

    # graph the first to points - which are always both of value 1
    xSz = 1     # the size, or width of each point, along the x-Axis
    ySz = yScale / float(n)
    # Plot first point
    dot = Oval( Point(1, x), Point(1+xSz, x+ySz))
    dot.setFill('green')
    dot.draw(win)
    # Plot second point
    dot = Oval( Point(2, y), Point(2+xSz, y+ySz))
    dot.setFill('green')
    dot.draw(win)

    # Since we have already started the sequence with the first two
    # values, we need to loop through the 'for' loop n-2 times. Since
    # the range function stops one value before the stopping value given,
    # the notation "range(1, n-1)" will do what we want - stop 2 values
    # lower than n

    for k in range(1, n-1):
        # Swap the values of x and y, to set up this next iteration
        # and calculate the next number in the sequence as an 
        # accumulator with the variable 'y'
        y, x, = x, y
        y = y + x

        # This print line is here for debugging, so you can see the
        # sequence evolve
        print "Next Fib num = ", y

        dot = Oval( Point((k+2), y), Point((k+2)+xSz, y+ySz))
        dot.setFill('green')
        dot.draw(win)

    # The final value is now 'x' since the values of w and y are
    # swapped inside the 'for' loop
    print "Final Fib num = ", x

    # Wait for the user to click the mouse before closing the window
    win.getMouse()
    win.close()

# run the program defined above in function main()
main()

Part 2: Random Snow Fall and Punxsutawney Phil

The most common error for this part of the homework was either not using the random.random() function, or using it incorrectly. For this function, you multiply the random value (that is between 0.0 and 1.0) by the scaling factor. Note this is different from the random.randrange() function for which you pass the desired range value to the function as a value placed inside the parentheses.

Can you predict the difference in values returned by the following statements?

rand1 = random.randrange(12)
rand2 = int(random.random() * 12)
rand3 = random.randrange(3, 12)
rand4 = int(random.random() * 12) + 3

One Possible Solution

# HW3_Snow.py
#
# J Cardell, Feb 16, 2011
#
# This program predicts the net snow on the ground after one month. The
# random number generator library is used, to generate both snow fall and
# snow melt. The results are plotted with very simple annimation.

from graphics import *
from random import *
from time import *

def main():

    print "This program predicts the amount of snow that will fall, ",
    print "and melt, over the next month"

    # Constant definition - name the constants you will be using and 
    # assign their values at the start of the program. This allows you to 
    # (1) know what every value is when it pops up in your code - a month
    # from now you might not remember what '31' meant, but if you give it a
    # clear name, you wil remember and (2) if you want to change the value,
    # especially when you use a constant value more than once in your code,
    # it is easy to find the one place where you need to assign the new value
    nDays = 31
    snowMax = 6   # for the random numbers, limit the fall and melt to 6"/day
    dotSz = 0.5   # the size of the points that will be graphed

    # Set up the graphing window
    winSnow = GraphWin("Snow on the Ground!", 1000, 500)
    winSnow.setBackground('LightYellow')
    # Scale the y-axis to span from -ySc to +ySc
    ySc = 20
    winSnow.setCoords(0, -ySc, nDays, ySc)

    # Draw x-axis for a visual reference on the graph. You do not need to do
    # this in HW3
    Xline = Line(Point(0, 0), Point(nDays, 0))
    Xline.draw(winSnow)

    snowNet = 0
    for k in range (nDays):
        sleep(0.5)
        snowFall = randrange(0,snowMax+1)
        snowMelt = int(random() * snowMax)
        snowNet = snowNet + snowFall - snowMelt

        # The factor of '2' used here is from trial and error given the y-axis
        # scaling
        dotFall = Oval(Point(k, snowFall), Point(k + dotSz/2, snowFall + dotSz))
        dotMelt = Oval(Point(k, snowMelt), Point(k + dotSz/2, snowMelt + dotSz))
        dotNet = Oval(Point(k, snowNet), Point(k + dotSz, snowNet + dotSz*2))

        dotFall.setFill('turquoise')
        dotMelt.setFill('MediumPurple')
        dotNet.setFill('magenta')
        dotNet.setOutline('black')

        dotFall.draw(winSnow)
        dotMelt.draw(winSnow)
        dotNet.draw(winSnow)

    print "The final net snow is", snowNet,"inches"

    # Wait for the user to click the mouse before closing the window
    winSnow.getMouse()
    winSnow.close()

# Call the 'main()' function defined above, so it executes
main()