A201

Assignment 7

Printing Tables

Pair programming on this lab and assignment.

In Lab

Here's today's "fill in the dots" game:

def lightening_distance(seconds):
    """
    Return an estimate of the distance, in miles, to a lightening bolt, given
    that sound travels about 1,100 feet per second and there are 5,270 feet
    per mile.
    >>> lightening_distance(3)
    0.62618595825426948
    >>>
    """
    #.

def and_fun(a, b):
    """
    Return True if a and b are both true values, and False otherwise.
    Do not use boolean a operator.
    >>> and_fun(True, False)
    False
    >>> and_fun(1, 2)
    True
    >>>    
    """
    #.
    #.
    #.
    #.
    #.
    #.
    #.

def denomination_string(n, denomination_name):
    """
    Returns a string of the form "<n> <name>", where
    <n> represents the integer n and <name> is the plural form of the
    denomination name. Denominations are "quarter", "dime",
    "nickel", and "penny".
    >>> denomination_string(3, 'penny')
    '3 pennies'
    >>> denomination_string(1, 'penny')
    '1 penny'
    >>> denomination_string(2, 'nickel')
    '2 nickels'
    >>>
    """
    #.
    #.
    #.
    #.
    #.
    #.
    #.

def make_change(amount):
    """
    Returns a string indicating the number of quarters, dimes, nickels,
    and pennies that make perfect change for the given amount (in cents).
    Appropriate singular and plural forms for the coin denominations are used.
    >>> make_change(67)
    '2 quarters, 1 dime, 1 nickel, 2 pennies'
    >>>
    """
    quarters = amount / 25 
    amount = amount % 25
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.

def pi(delta):
    """
    Return an estimate of the value of pi, which is the sum of the infinite
    series of terms beginning with

        4/1 - 4/3 + 4/5 - 4/7 + ...

    Quit when a term whose absolute value is less than delta has been added
    to the series.

    The pattern of the terms in the series repeats indefinitely: the divisor of
    each term is two greater than the previous term, and the sign of the terms
    alternate. The more terms are added the more accurate the value of pi is
    (until the computation is limited by the accuracy of floating point
    arithmetic).

    >>> pi(.001)
    3.1420924036835256
    >>>
    """
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.


Hints

  • make_change

    • use the denomination_string function
  • pi: Use three variables that change with each loop iteration:

    • the sum of terms computed so far
    • the sign of the next term, 1 or -1
    • the next term's denominator

    Do the following in each iteration of the loop:

    • compute the absolute value of the next term
    • add this value times the sign to the sum
    • break out of the loop after adding a term whose value is less than delta
    • add two to the divisor
    • change the sign of the sign variable

Before you leave, turn in your application file as Lab 7 using Oncourse. Don't forget to include a comment on the first line that contains the names and usernames of both team members and your lab section start time.

Also before leaving be sure to read the assignment below. Ask your lab instructor if the assignment is not clear.

Assignment

Due 3pm, February 28th

Just fill in the dots...

import random
import calendar

def right_justify(n, string):
    """
    Returns the string with enough blanks added at the beginning 
    to make it n characters long.
    >>> right_justify(6, 'spam')
    '  spam'
    >>>
    """
    return ' ' * (n - len(string)) + string

def print_powers_line(num_powers):
    """
    Print the first num_powers powers of two on one line, separated by spaces
    (with an extra space at the end).
    >>> print_powers_line(5)
    2 4 8 16 32 
    >>>
    """
    count = 1 
    #.
    #.
    #.
    #.
    print line

def print_powers_wrapped(num_powers, column_width, num_columns):
    """
    Print the first n powers of two, each right justified in the indicated
    number of columns, with the indicated number of columns per line.
    >>> print_powers_wrapped(30, 10, 5)
              2          4          8         16         32
             64        128        256        512       1024
           2048       4096       8192      16384      32768
          65536     131072     262144     524288    1048576
        2097152    4194304    8388608   16777216   33554432
       67108864  134217728  268435456  536870912 1073741824
    >>>
    """
    #.
    #.
    #.
    while count <= num_powers:
        if column > num_columns:
            print line
            line = ''
            column = 1        
        #.
        #.
        #.
    #.
    #.

def print_calendar(year, month):
    """
    Print a calendar for the given year and month (1-12).
    >>> print_calendar(2008, 2)
                     1  2
      3  4  5  6  7  8  9
     10 11 12 13 14 15 16
     17 18 19 20 21 22 23
     24 25 26 27 28 29
    >>>
    """
    # Assign the variable first_day a number indicating the day
    # of the week with 0 for Monday, etc.,
    # and assign the variable num_days the number of days in the month.
    first_day, num_days = calendar.monthrange(year, month)

    first_day = (first_day + 1) % 7 # 0 for Sunday, 1 for Monday, etc.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.

def guess_number():
    """    
    The player enters a level of play: a positive integer, call it level.  The
    computer then guesses an integer between 1 and 2**level.  After this the
    player tries to guess the computer's number. The computer response indicates
    if the guess is correct, too high, or too low.

    When the user finds the number, the number of questions asked is printed.
    If this number is less than the level, the message 'You were lucky!' is
    printed, if it is equal to the level, to the message 'Perfect play!' is printed, 
    and if it is less than half-again (1.5 times) the level, 'Not bad.' is printed,
    and otherwise (the level 1.5 times the level or greater) 'Not so good.' is printed. 

        Enter game level (a positive integer): 4
        I'm thinking of an integer between 1 and 16.
        Your guess: 8
        That's too high.
        Your guess: 4
        That's too low.
        Your guess: 6
        That's too high.
        Your guess: 5
        That's it!
        It took you 4 tries to find my number.
        Perfect play!
    """
    level = int(raw_input('Enter game level (a positive integer): '))
    limit = 2 ** level
    print "I'm thinking of an integer between 1 and", str(limit) + '.'
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.
    #.


Submit your solution via Oncourse as usual. Don't forget to include a comment on the first line that contains the names and usernames of both team members and your lab section start time.

Hints

  • print_powers_line
    • Use a counting and accumulating loop.
    • The line is accumulated in a string and then printed.
  • print_powers_wrapped
    • This is also a counted accumulating loop, but with some differences. Besides the counter that controls the loop termination, and is used to compute the powers of two (as in the last function), there is another counter that keeps track of the current column. When that is more than the number of columns we want, the line is printed and the line and column count variables are reset.
    • When the loop terminates, any characters accumulated in the line variable need to be printed. If the line is empty it is better not to print the empty line, for it would be inconsistent for the output of the function to sometimes end with a blank line and sometimes not. This is a detail, but in programming, as most other endeavors, good style requires attention to detail.
    • Frequently tables involve nested loops, but it is easiest to do this one with a single loop that "resets" the line in this manner.
  • print_calendar
    • The easiest way to program this is with a structure very similar to the print_powers_wrapped function. After all, a calendar is basically a list of day numbers that wrap to start each week on a new line.
    • The "calendrical" calculation that determines which day of the week a month starts on is done by the monthrange function in Python's calendar module. This function also returns the number of days in the month, and uses a mechanism we won't study in this course to return both values from one function call. The program skeleton provided uses "multiple-value assignment" syntax to store these values in the variables first_day and num_days simultaneously. Your Python text uses multiple-value assignment a few times, but you are not responsible for it in this course.
    • Another complication is that the first_day value returned by the monthrange function indicates Monday as 0, Tuesday as 1, and so on. The calendar we print is in the most common format, with Sunday in the first column, so the line following the function call uses a nifty trick with modulus arithmetic to convert the value in first_day to a representation in which Sunday is 0, Monday 1, and so on.
  • guess_number
    • Since there is no limit to how badly the player will guess, this is an indefinite loop that you break out of when the player finally guesses right the number.
    • FYI: Perfect play is obtained by reducing the number of possibilities in half with each question, using an algorithm known to computer scientists as "binary search". Perfect play thus involves using a systematic algorithm, not guessing. Of course in this game attempting perfect play is the player's challenge, not the program's. The program just keeps score.
    • FYI: Finding something among a number of equally-likely and ordered possibilities in fewer tries than the log, base 2, of the number of possibilities (the level in this game) is only possible with good luck.