15110 Spring 2013 [Kaynar/Gunawardena]

Programming Assignment 2 - due Tuesday, January 29 by 11:59 pm

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 pa2 directory under ~/private/15110 for this assignment. That is, the new directory pa2 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 Ruby source file (that is, a text file containing Ruby code) for each of the problems below. You should store all of these files in a folder named pa2, which you will zip up and submit.

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).

The Formulas

Write Ruby functions to calculate each formula as indicated below. The calculations should be performed with the full precisision shown in the examples.

  1. [2 point] Programs can be written to help people accomplish tasks. An example would be a function used to calculate the amount of tip you should leave your waiter after a meal. Given the function

    T=pr
    where T is the tip amount in dollars, p is the price of the meal in dollars, and r is the rate of tips as a decimal.
    1. Use a calculator to determine the amount of tip in dollars that should be left for the waiter given that the bill was $53.29 and the current tip rate is 18.25% .

      Your answer should be $9.725425. This part of the question does not require a submission from you; it is for exercise only.

    2. Define a Ruby function tip(p,r) that returns the amount of tip that is expected to be placed on the table assuming the price of the meal is equal to p and the tip rate is equal to r. Put the function in a file called tip.rb.

    3. Suppose you and two of your friends go out to a "half-price" dinner one night. You ask the waiter to separate your check so that you each only have to pay for your portion of the bill. Because you are such a nice friend, you offer to pay the tip for both of your friends as well as yourself. After dinner, the checks come and the totals for each of you are as follows:

      Your bill was $11.03.

      Your friend, Eats-a-lot Smith, had a bill of $23.74.

      Your other friend, Nibbles Doe, had a bill of $3.12.

      Define a Ruby function dinner(), in the same file tip.rb (i.e., the tip.rb function now includes the function tip(p,r) followed by the function dinner(). The function dinner() must use (i.e., call) the function tip(p,r) with the right argumens to compute and print out the amount of tip in dollars that you should leave for the waiter. In Pittsburgh, the current tip rate is 17.8%. (Note: For full credit, you must call the tip function at least once. Do not simply recalculate what the tip function should be doing for you.) The function should return nil in all cases.

      Example usage:

      >> load "tip.rb"
      => true
      >> tip(100, 0.19)
      => 19.0
      >> dinner()
      6.74442=> nil
      

  2. [2 point] A quadratic equation ax2+bx+c=0 can be solved for x by calculating:

    x=b±b24ac2a

    In quadratic.rb, define a Ruby function quadratic(a,b,c), which takes the constants a, b, and c and calculates and prints the two values of x for which the equation holds using exactly the same format as shown in the examples below. You may assume that b24ac is non-negative, and the function should output the same solution twice when b24ac=0. In all cases, the function should return nil. (Note: For those of you who know about Math.sqrt(expr), for full credit on this question, don't use it.)

    Example usage:

    >> load "quadratic.rb"
    => true
    >> quadratic(1.0,3.0,-4.0)
    [x1: 1.0, x2: -4.0]
    => nil
    >> quadratic(1,4,4)
    [x1: -2.0, x2: -2.0]
    => nil
    
  3. [2 points] The operators / and % are most commonly used for division and getting the remainder, respectively. Let us observe the following with respect to integer division and modular arithmetic using modulus 10:

    Given this information, write a Ruby function called digit(num, pos) in the file digit.rb that takes in any positive number num and the position of the desired digit pos and returns the digit in the desired position. Assume that the function will always be called with a value for pos that is greater than zero and no larger than the number of digits in num. Furthermore, assume that a pos of 1 indicates the rightmost digit, a pos of 2 indicates the digit second from the right and so on.

    Example usage:

    >> load "digit.rb"
    => true
    >> digit(73,1)
    => 3
    >> digit(9824759837450, 8)
    => 5
    
  4. [2 points] Consider a quadratic polynomial function of the form:

    f(x)=ax2+bx+c.

    In list_quad1.rb, define a Ruby function called list_quad1(a, b, c) that prints a list of the values of f(x) for x = 0 to x = 30 (inclusive), given the coefficients of the polynomial in the order shown. Your function should use a loop rather than repeating the code for the calculation 31 times. Use the formula directly to compute these values. The function should always return nil.

    For example, if your polynomial is f(x)=3x2+4x3, then you should observe the following output upon loading the file.

    >> load "list_quad1.rb"
    => true
    >> list_quad1(3,4,-3) 
    -3
    4
    17
    
    2817
    => nil
    

    Be sure to test your function using a few more polynomials besides this one to be more confident that your function is correct.

  5. [2 points] An alternate way to compute the values of a polynomial function is to use the method of finite differences that was used in Babbage's Difference Engine.

    In list_quad2.rb, define a Ruby function called list_quad2(d2f0, df0, f0) that prints a list of the values of f(x) for x = 0 to x = 30 (inclusive), given the values of Δ2f(0), Δf(0), and f(0), respectively. Your function should use the method of finite differences to compute the function values. The function should always return nil.

    For example, consider the calculation of the values for the polynomial, f(x)=3x2+4x3. Using the method in described in the lecture, we can compute the Δ functions by hand to be:

    Δ2f(0)=6
    Δf(0)=7
    f(0)=-3

    Thus, list_quad2(6, 7, -3) can be used to list the values for this polynomial:

    >> list_quad2(6, 7, -3)
    -3
    4
    17
    
    2817
    => nil
    

    Be sure to test your function using a few more polynomials besides this one to be more confident that your function is correct.

Submission

You should now have a pa2 directory that contains the files tip.rb, quadratic.rb, digit.rb, list_quad1.rb, and list_quad2.rb each containing the corresponding function. Zip up your directory and hand it in.