Programming Assignment 1 - due Friday, June 2

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. [1 point] According to Einstein's special theory of relativity, the energy content of a body can be computed from its mass by using the equation, \[e = mc^2,\] where \(c\) is the speed of light. (Note, the speed of light is exactly \(2.99792452 \times 10^8\) meters per second.)

    1. Use a calculator to determine the energy content in joules of a body weighing \(2.5 \times 10^{-8}\) kg.

      Note that, since \(1 \text{J} = 1 \frac{\text{kg} \cdot \text{m}^2}{\text{s}^2}\), one can just plug into the equation \(2.5 \times 10^{-8}\) for \(m\) and \(2.99792452 \times 10^8\) for \(c\) without performing any unit conversions.

      Your answer should be \(2.2468878569 \times 10^9\).

    2. Create a text file, energy.rb, that defines a Ruby function energy(m) which computes and returns the amount of energy content in joules of a body weighing m kilograms.

    This energy(m) function should be able to be used in irb as follows:

    >> load "energy.rb"
    => true
    >> energy(2.5e-8)
    => 2246887856.90431
    >> energy(2)
    => 1.79751028552345e+17
    
  2. [1 point] According to ohm's law, the current \(I\) flowing through a conductor between two points can be calculated from the conductor's resistance \(R\) and the potential difference \(V\) across those points by using the equation: \[I = \frac{V}{R}\] If the potential difference \(V\) is measured in volts and resistance \(R\) is measured in ohms, the resulting current \(I\) will be in amperes.

    In current.rb, define a Ruby function current(v,r) that calculates and prints (in the format shown below) the current flowing through a conductor between two points whose potential difference is v volts when the resistance of the conductor is r ohms. The function should return nil in all cases.

    Example usage:

    >> load "current.rb"
    => true
    >> current(12.0,2.5)
    The current is 4.8 amperes.
    => nil
    >> current(110,7)
    The current is 15.7142857142857 amperes.
    => nil
    
  3. [1 point] 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}\]

    (Note: \(r\) should be a decimal fraction, so 0.05 would be used to represent a 5% annual interest rate.)

    In continuous_interest.rb, define a function continuous_interest(present_value, interest_rate, years) that calculates and returns the future value that a deposit of present_value would grow to after years years when interest is compounded continously at an annual rate of interest_rate. (Use Math::E for \(e\).)

    Example usage (corrected):

    >> load "continuous_interest.rb"
    => true
    >> continuous_interest(10231.51, 0.05, 5)
    => 13137.5188910948
    >> continuous_interest(998.95, 0.10, 10)
    => 2715.42763253916
    
  4. [1 point] A quadratic equation \(ax^2 + bx + c = 0\) can be solved for \(x\) by calculating:

    \[x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\]

    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 \(b^2 - 4ac\) is non-negative, and the function should output the same solution twice when \(b^2 - 4ac = 0\). In all cases, the function should return nil. (Hint: Math.sqrt(expr) evaluates to the square root of expr.)

    Example usage:

    >> load "quadratic.rb"
    => true
    >> quadratic(1.0,3.0,-4.0)
    x1: 1.0
    x2: -4.0
    => nil
    >> quadratic(4,4,1)
    x1: -0.5
    x2: -0.5
    => nil
    
  5. The volume of a cone can be calculated from the radius \(r\) of its base and its height \(h\) using the formula:

    \[\frac{1}{3}\pi r^2 h\]
    1. [1 point] In cone.rb, write a Ruby function cone_volume(radius,height) that calculates and returns the volume of a cone whose base's radius is radius and whose height is height. (Use Math::PI for \(\pi\).)

    2. [1 point] Consider the three-dimensional object shown in the figure to the right, which consists of two cones whose heights are 20m and 30m, respectively, and which share a base, whose radius is 7m.

      In cone.rb, define a Ruby function print_object_volume() that calculates the total volume occupied by that object (i.e., the total volume occupied by the two cones that make up the object). It should return nil after printing the following line of text:

      The total volume of the two cones is XXXX.XXXXXXXXXXX.
      

      (Replacing XXXX.XXXXXXXXXXX with the calculated volume.)

      Your print_object_volume() function should be defined without directly calculating the volume of the cones. Rather you should call your cone_volume function you wrote for part a.

  6. [2 points] Consider a quadratic polynomial function of the form:

    \[f(x) = ax^2 + 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 = 35 (inclusive), given the coefficients of the polynomial in the order shown. (You should use a loop rather than repeating the code for the calculation 36 times.) Use the formula directly to compute these values. The function should always return nil.

    For example, if your polynomial is \(f(x) = 4x^2 - 3x + 5,\) then the output would look like:

    >> load "list_quad1.rb"
    => true
    >>  list_quad1(4,-3,5) 
    5
    6
    15
    32
    57
    90
    131
    180
    237
    302
    375
    
    \(\vdots\)
    4800
    => nil
    

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

  7. [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 = 35 (inclusive), given the values of \(\Delta^2{}f(0)\), \(\Delta{}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) = 4x^2 -3x + 5.\) Using the method in described in the lecture, we can compute the by hand that \(\Delta{}f(x) = 8x + 1\) and \(\Delta^2{}f(x) = 8\). So the initial values of these functions at \(x = 0\) are: \(\Delta^2f(0) = 8\), \(\Delta f(0) = 1\), and \(f(0) = 5\). Thus, list_quad2(8,1,5) can be used to list the values for this polynomial:

    >>  list_quad2(8,1,5)  
    5
    6
    15
    32
    57
    90
    131
    180
    237
    302
    375
    
    \(\vdots\)
    4800
    => nil
    

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