15110 Principles of Computing - Summer Two 2014

Programming Assignment 3 - due Tuesday, July 8 by 9:00AM

Note: You are responsible for protecting your solutions to these problems from being seen by other students both physically (e.g., by looking over your shoulder) and electronically. In particular, since the lab machines use the Andrew File System to share files worldwide, you need to be careful that you do not put files in a place that is publicly accessible.

If you are doing the assignment on the Gates-Hillman Cluster machines we use in lab or on unix.andrew.cmu.edu, our recommendation is that you create a pa3 directory under ~/private/15110 for this assignment. That is, the new directory pa3 is inside a directory called 15110, which is inside the directory called private, which is inside your home directory. (Every new andrew account is set up with a private subdirectory within the account's home directory that only that account can access.) Please refer to Setting up Directories for information about managing your directories.

Overview

For this assignment, you will create a Python source file (that is, a text file containing Python code) for each of the problems below. You should store all of these files in a folder named pa3, which you will zip up and submit.

This assignment will make you practice the control structures we have learned so far (conditionals, for loops, while loops) and make you learn how to move from a given algorithm to Python code.

As you will discover this semester, computer programs are rarely correct when they are first written. They often have bugs. In addition to writing the code, you should test your code on multiple inputs, for which you independently know the correct output (e.g., by plugging the inputs into a calculator).

Problems

  1. [1 point] Three numbers \(x, y\), and \(z\) are called a Pythagorean triple if \(x^2 + y^2 = z^2\). For example, the triple 3, 4, and 5 is a Pythagorean triple since 9 + 16 = 25. In a file named p_triple.py , write a Python function p_triple(x, y, z) that takes 3 integers as arguments and prints a message saying whether the three arguments form a Pythagorean triple. (Note that the three parameters represent the values x, y and z in that specific order.) Your function must return None.

    Example Usage:

    > python3 -i p_triple.py
    >>> p_triple(3,4,5)
    3, 4 and 5 form a Pythagorean triple
    >>> print(p_triple(3,4,5))
    3, 4 and 5 form a Pythagorean triple
    None
    >>> p_triple(6,8,10)
    6, 8 and 10 form a Pythagorean triple
    >>> p_triple(5,12,13)
    5, 12 and 13 form a Pythagorean triple
    >>> p_triple(5,11,14)
    5, 11 and 14 do not form a Pythagorean triple
    		
    
    		

  2. [1 point] In a file named largest.py define a Python function largest(x,y,z) that takes three integers as arguments and returns the largest one among them. You may assume that the function will always be called with three numbers that are not equal to one another. You can use the Boolean operator and if you need to use a compound Boolean expression in the test of a conditional. You may not use the built-in function max.

    Example Usage:

    > python3 -i largest.py
    >>> largest(300,200,500)
    500
    >>> largest(2357,1589,1000)
    2357
    
    				

  3. [2 points] Doubling Time.

    For an account with a deposit of \(P\) dollars that earns interest compounded continuously at an annual rate of \(r\) for \(t\) years, the final amount \(A\) of the account is given by the formula:

    \[A = Pe^{rt}\]

    The bisection method can be used to approximate how much time (in years) that would be required for an initial deposit to double (i.e., finding a value of \(t\) for which \(0 = e^{rt} - 2\)). It works by maintaining a lower and upper bound for a range in which the desired value of \(t\) is known to exist. In each iteration, it finds the half-way point of that range and determines whether the desired value of \(t\) is above or below that half-way point. The algorithm stops when the range is smaller than some threshold.

    The bisection method can be realized using the following algorithm, which is parameterized by rate:

    1. Set low to 0.
    2. Set high to 100.
    3. Set guess to 50.
    4. Set guess_error to 50.
    5. While guess_error is greater than 0.00001, do the following:

      1. If \(e^{\textit{rate}\times\textit{guess}} - 2\) is at least 0:
        • Set high to the value of guess.
        Otherwise, (if you did not just set high)
        • Set low to the value of guess
      2. Set guess to \(\frac{\textit{high} + \textit{low}}{2}.\)

      3. Set guess_error to \(\frac{\textit{high} - \textit{low}}{2}.\)

    6. Display guess as your answer.

    Write a Python function called doubling(rate) in doubling.py that implements this algorithm giving the result as shown below. You should insure that all divisions are floating point division. You may assume that the interest rate will be at least 0.00001.

    HINT: To use the mathematical e function, import the math module and use the math.exp function.

    Example:

    > python3 -i doubling.py
    >>> doubling(0.1)
    Number of years for your investment to double: 6.931476294994354
    >> doubling(0.05)
    Number of years for your investment to double: 13.862945139408112
    >> doubling(0.01)
    Number of years for your investment to double: 69.31471079587936
    
  4. [2 points] ASCII-art.

    By printing out different characters at different locations, it is possible to create images. This is sometimes called ASCII art, and works best in a terminal that uses a fixed-width font. Regular shapes, such as the triangle shown below, are easy to create algorithmically.

    				*
    				* *
    				*   *
    				*     *
    				*       *
    				* * * * * *
    				

    This right triangle can be created using the following algorithm, which requires the triangle's height (that is, the number of lines in the triangle). It assumes that height is non-negative.

    1. Print 1 asterisk("*") on the first line (row 1).
    2. For the next \(height-2\) lines
      1. Print 1 asterisk
      2. Print \(2*row-3\) spaces, where \(row\) represents the current row number that is being printed
      3. Print 1 asterisk
    3. Print \(height\) copies of an asterisk followed by a space ("* ") for the last line.

    Note that a denegarate case of a right triangle would arise when $height =1$. In that case, we would not need to perform all of the steps described above; we would print a single asterisk.

    Implement this algorithm as a Python function make_triangle(height) and store it in file make_triangle.py. Your function must return None.

    Hint: There are many ways to solve the problem. One of them involves a nested loop (a loop inside of a loop). If you use a loop inside of another loop, make sure to use a different loop variable for each loop (e.g. if the outer loop uses "i", the inner loop can use "j").

    Example usage:

    > python3 -i make_triangle.py
    >>> make_triangle(5)
    *
    * *
    *   *
    *     *
    * * * * *
    
    >>> make_triangle(8)
    *
    * *
    *   *
    *     *
    *       *
    *         *
    *           *
    * * * * * * * *
    
  5. [4 points]

    Pay table

    Hourly workers typically earn overtime when they work more than 40 hours per week. Suppose that overtime pay is 150 percent of the regular salary for the additional hours.

    1. [2 points] In a file named wages.py write a Python function called pay(wage,hours) that takes as input wage and hours, respectively, representing the hourly wage and the hours worked for a week and returns the wages earned for the week. You can assume that hours are recorded as whole numbers. For example, 4.5 hours is not a legal argument while 4 is.

      Example usage:

      > python3 -i wages.py
      >>> pay(10,15)
      150
      >>> pay(10,45)
      475.0
      >>> pay(12,44)
      552.0
      
    2. [2 points] Also in the file wages.py, write another Python function called pay_table() that displays a table of the pay for an employee for wages of 10 dollars per hour up through 30 dollars per hour (inclusive) in steps of 2 dollars, and hours worked from 30 to 60 (inclusive) in steps of 5 hours. Your output should line up as closely as shown for maximum credit. Your function should call the pay function you wrote for the previous part. It should not recompute the pay itself.

      HINT: To get the pay amounts to line up in the table, you will need an if statement.

      Example usage:

      >python3 -i wages.py
      >>> pay_table()
               30     35     40     45     50     55     60     hours
      $10:  300.0  350.0  400.0  475.0  550.0  625.0  700.0 
      $12:  360.0  420.0  480.0  570.0  660.0  750.0  840.0 
      $14:  420.0  490.0  560.0  665.0  770.0  875.0  980.0 
      $16:  480.0  560.0  640.0  760.0  880.0 1000.0 1120.0 
      $18:  540.0  630.0  720.0  855.0  990.0 1125.0 1260.0 
      $20:  600.0  700.0  800.0  950.0 1100.0 1250.0 1400.0 
      $22:  660.0  770.0  880.0 1045.0 1210.0 1375.0 1540.0 
      $24:  720.0  840.0  960.0 1140.0 1320.0 1500.0 1680.0 
      $26:  780.0  910.0 1040.0 1235.0 1430.0 1625.0 1820.0 
      $28:  840.0  980.0 1120.0 1330.0 1540.0 1750.0 1960.0 
      $30:  900.0 1050.0 1200.0 1425.0 1650.0 1875.0 2100.0 
      

    Submission

    You should now have a pa3 directory that contains the files p_triple, largest.py, doubling.py, make_triangle.py, and wages.py each containing the corresponding function(s). Zip up your directory and hand it in.