Last Updated: 2017-10-01 Sun 16:21

CSCI 1103 Project 2: Conditions, Loops, Arrays

CODE DISTRIBUTION: p2-code.zip

CHANGELOG: Empty

1 Introduction

Moving on from straight-line code, conditionals and loops provide the ability to jump around in programs. This opens up the full power of what can be computed but makes programs more difficult to understand. These problems require conditionals, loops, and in some cases a combination of them. Also covered is basic input into an array and looping over its contents to analyze its elements.

2 Download Lab Code and Setup

As in Lab01, download the code pack linked at the top of the page. Unzip this which will create a folder and create your files in that folder.

File State Notes
TextIO.java Provided Allows easy input calls like TextIO.getInt()
RichterTests.java Testing Tests for Problem 1
MultTableTests.java Testing Tests for Problem 2
SymmetricSeqTests.java Testing Tests for Problem 3
KTests.java Testing Test functions, runs all project tests from command line
junit-1103.jar Testing For testing, don't try to edit this one
Richter.java Create Create this file for Problem 1
MultTable.java Create Create this file for Problem 2
SymmetricSeq.java Create Create this file for Problem 3

3 Problem 1: Richter Scale

The Richter Scale is among the scales used to measure the magnitude of earthquakes. Below is a table of ranges of magnitudes M of earthquakes and brief descriptions of the effects of an event in that range.

Magnitude (M) Effects
0.0 ≤ M < 2.0 Not felt by most people
2.0 ≤ M < 3.0 Felt slightly by some people
3.0 ≤ M < 4.0 Often felt by people, but very rarely causes damage.
4.0 ≤ M < 5.0 Noticeable shaking, felt by most people. None to minimal damage.
5.0 ≤ M < 6.0 Felt by everyone. None to slight damage.
6.0 ≤ M < 7.0 Damage to a moderate number of buildings, poorly constructed buildings may collapse.
7.0 ≤ M < 8.0 Major damage to buildings, structures likely to be destroyed.
8.0 ≤ M At or near total destruction - severe damage or collapse to all buildings.

For reference, the recent 2017 Mexico Earthquake had a magnitude of 7.1 (though this measure is on a slightly different scale). It toppled many buildings and caused widespread damage.

This problem will convert the above table into an easy lookup for users who type in a magnitude and get back a description of the effects.

3.1 Demo

> javac Richter.java 

> java Richter
Enter magnitude of earthquake (ex 5.8):
-3.8
-3.8 : Invalid magnitude, must be > 0.0

> java Richter
Enter magnitude of earthquake (ex 5.8):
2.345
2.3 : Felt slightly by some people

> java Richter
Enter magnitude of earthquake (ex 5.8):
6.872
6.9 : Damage to a moderate number of buildings, poorly constructed buildings may collapse.

> java Richter
Enter magnitude of earthquake (ex 5.8): 
7.1
7.1 : Major damage to buildings, structures likely to be destroyed.

> java Richter
Enter magnitude of earthquake (ex 5.8): 
10.1
10.1 : At or near total destruction - severe damage or collapse to all buildings.

3.2 Basic Approach

Create a file Richter.java.

  • Prompt the user to enter a magnitude
  • Retrieve this floating point number using TextIO
  • Use a set of if/else if conditions to check the magnitude and print out one message from the table above.
  • Preceding each message, print the magnitude that was entered with 1 digit beyond the decimal place as in
    Enter magnitude of earthquake (ex 5.8):
    2.374
    2.4 : Felt slightly by some people
    

    printf() is useful for this using a format specifier.

  • Make sure to check in one condition for magnitudes below 0 which are invalid and should give a message like
    -3.8 : Invalid magnitude, must be > 0.0
    

3.3 Problem 1 Richter Manual Inspection Criteria (15%)   grading

The criteria below will be examined by graders to account for part of your grade.

Wgt Criteria
2% Make use of the TextIO class to get input from the user
3% Make use of printf() to produce 1 digit beyond the decimal place
5% Make use of a series of if/else if conditions to print a single table entry
5% Clearly include a case checking for negative magnitudes
15% Total weight for these criteria

4 Problem 2: Multiplication Tables

Most young students learn basic arithmetic initially through memorization: it's hard to do more complex math if one does not know basic combinations like 5 times 3. For this, multiplication tables are among the most common tools though the size of table varies from region to region (10 by 10 is common, but some areas go up to 12 by 12 or larger).

This problem will generate arbitrary sized multiplication tables like the following.

        1   2   3   4   5   6   7   8   9  10 
    +-----------------------------------------
  1 |   1   2   3   4   5   6   7   8   9  10 
  2 |   2   4   6   8  10  12  14  16  18  20 
  3 |   3   6   9  12  15  18  21  24  27  30 
  4 |   4   8  12  16  20  24  28  32  36  40 
  5 |   5  10  15  20  25  30  35  40  45  50 
  6 |   6  12  18  24  30  36  42  48  54  60 
  7 |   7  14  21  28  35  42  49  56  63  70 
  8 |   8  16  24  32  40  48  56  64  72  80 
  9 |   9  18  27  36  45  54  63  72  81  90 
 10 |  10  20  30  40  50  60  70  80  90 100

Nested loops will be required to do this where an outer loop produces each row while the inner loop works across each row to generate each table element.

4.1 Demo

> java MultTable
Enter max rows and columns: (ex: 4 6)
3 5
        1   2   3   4   5 
    +---------------------
  1 |   1   2   3   4   5 
  2 |   2   4   6   8  10 
  3 |   3   6   9  12  15 

> java MultTable
Enter max rows and columns: (ex: 4 6)
6 2
        1   2 
    +---------
  1 |   1   2 
  2 |   2   4 
  3 |   3   6 
  4 |   4   8 
  5 |   5  10 
  6 |   6  12 

> java MultTable
Enter max rows and columns: (ex: 4 6)
8 9
        1   2   3   4   5   6   7   8   9 
    +-------------------------------------
  1 |   1   2   3   4   5   6   7   8   9 
  2 |   2   4   6   8  10  12  14  16  18 
  3 |   3   6   9  12  15  18  21  24  27 
  4 |   4   8  12  16  20  24  28  32  36 
  5 |   5  10  15  20  25  30  35  40  45 
  6 |   6  12  18  24  30  36  42  48  54 
  7 |   7  14  21  28  35  42  49  56  63 
  8 |   8  16  24  32  40  48  56  64  72 

>

4.2 Basic Approach

This problem requires some careful formatting to match the tests so take care to follow the instructions closely and make use of the provided format strings.

Create a file MultTable.java.

  • Prompt a user for 2 integers and read them using TextIO.java
  • Create the header which is the top part of the table like
            1   2   3   4   5   6   7   8   9  10 
        +-----------------------------------------
    

    The header can vary in size so will require a loop.

    • The upper left is 6 spaces as in
      "      "
      

      and should always be printed

    • The remainder of the header numbers are printed in a field of width 3, right justified, and space padded, with one space to the right. This is done easily with the following printf() format string
      "%3d "
      
    • Remember to loop over the number of columns: 10 columns give 1 to 10, 12 columns gives 1 to 12
    • To complete the header, print the horizontal divider line. It starts with the string
      "    +-"
      

      and then has 4 dashes for each column as in

      "----"
      

      Use a loop over columns to produce the proper number of dashes

  • Next set up a nested loop to print the table entries
    • The outer loop iterates over the number of rows. Each iteration will complete a row.
    • At the beginning of each row, print the row number along with a vertical bar and space. Use the format specifier
      "%3d | "
      
    • Then start the inner loop which iterates over the number of columns. It should print each table entry which is the row# multiplied by the column#. Print the table entry with the same specifier as the table header as in
      "%3d "
      
  • At the end of every row make sure to print newlines as in
    System.out.printf("\n");
    

    as printf() does not print line breaks by default.

4.3 Problem 2 MultTable Manual Inspection Criteria (15%)   grading

The criteria below will be examined by graders to account for part of your grade.

Wgt Criteria
5% Comments indicate the loops which print the table header
5% Comments indicate the loops which print the main table and entries
5% Clear style is used in loops which follows a regular pattern of progression over rows/cols
15% Total weight for these criteria

5 Problem 3: Symmetric Sequence

Arrays and loops go hand in hand: arrays store multiple values of the same kind and loops allow one to traverse all the elements of the array in a regular pattern. This problem exercises these two abilities.

A symmetric sequence is a series of numbers which is identical if read either from the beginning to end or from end to beginning. Here are examples of a symmetric sequences and non-symmetric sequences.

SYMMETRIC, length 7
value: 17 22 38 59 38 22 17
index:  0  1  2  3  4  5  6

NOT SYMMETRIC, length 7
value: 17 22 38 59 65 22 17
index:  0  1  2  3  4  5  6
index 2 (38) does not match index 4 (65)

SYMMETRIC, length 8
value: 15 25 55 10 10 55 25 15
index:  0  1  2  3  4  5  6  7

NOT SYMMETRIC, length 8
value: 12 25 55 10 12 32 25 15
index:  0  1  2  3  4  5  6  7
index 0 (12) does not match index 7 (15)
index 2 (55) does not match index 5 (32)
index 3 (10) does not match index 4 (12)

This problem develops a program that reads in a sequence and determines if it is symmetric or not; if not, the detected problems will be printed.

5.1 Demo

> javac SymmetricSeq.java

> java SymmetricSeq
Enter length of sequence (ex: 7): 
4
Enter 4 integers:
1 3 5 9
seq[0] != seq[3]
seq[1] != seq[2]
NOT Symmetric

> java SymmetricSeq
Enter length of sequence (ex: 7): 
4
Enter 4 integers:
1 3 3 1
Symmetric

> java SymmetricSeq
Enter length of sequence (ex: 7): 
7
Enter 7 integers:
1 4 5 9 5 4 1
Symmetric

> java SymmetricSeq
Enter length of sequence (ex: 7): 
7
Enter 7 integers:
1 4 5 9 9 4 1
seq[2] != seq[4]
NOT Symmetric

> java SymmetricSeq
Enter length of sequence (ex: 7): 
7
Enter 7 integers:
2 4 5 9 9 3 1
seq[0] != seq[6]
seq[1] != seq[5]
seq[2] != seq[4]
NOT Symmetric

>

5.2 Basic Approach

Create a SymmetricSeq.java file.

  • Prompt the user for the number of sequence elements which will be provided.
  • Read this using TextIO
  • Create an array of integers with the given size
  • Print a message that the user should type in all the numbers.
  • Enter a loop to read ALL the integers into the array. Within the loop, make TextIO calls to get integers from the user but do not print additional prompts for each integer.
  • Keep in mind that arrays are 0 indexed so for a sequence 7 long, read into elements 0, then 1, then 2, and so on up to index 6. Don't read into index 7 as it is out of bounds.
  • Once all integers are in the array, commence with an analysis for symmetry.
  • Loop over the array but use variables or indexing to examine related sequence elements. In a sequence that is 7 long, the indices to compare are
    • 0 to 6
    • 1 to 5
    • 2 to 4
    • 3 does not need to be compared (center element)
  • A good strategy is to realize that index 0 is compared to index array.length-1, 1 to array.length-2, and so forth.
  • Use an if condition to check if the two related elements are equal. If not print a message indicating they are not equal as in
    seq[1] != seq[5]
    

    Multiple such messages can be printed for a sequence with many problems.

  • If any two related elements are found to not be equal, set a boolean indicating that the sequence is not Symmetric. Initially this boolean is true but any discrepancy will change it to false.
  • At the end of the loop, use a condition to print Symmetric or NOT Symmetric based on the boolean that is set.

5.3 Problem 3 SymmetricSeq Manual Inspection Criteria (20%)   grading

The criteria below will be examined by graders to account for part of your grade.

Wgt Criteria
5% Make use of the TextIO class to get input from the user in a loop where needed
5% Comments clearly indicate the first phase of reading input from the user
5% Comments clearly indicate the second phase of analyzing the sequence for symmetry
5% A dynamic array is allocated based on user input; no fixed size arrays are used
20% Total weight for these criteria

6 Automatic Testing (50%)   grading

6.1 Running Tests

Run the tests associated with the project and ensure all of them pass. This can be done in DrJava by pressing the Test button when test files are open.

On the command line you can run all tests with the following commands.

On Unix/Mac platforms, use a terminal to run the following commands in the folder where your code exists.

> javac -cp .:junit-1103.jar KTests.java   #compile
> java -cp .:junit-1103.jar KTests         #run tests

On windows, use cmd.exe and change to the correct directory. Run the commands below where which use a semicolon (;) rather than a colon (:).

> javac -cp .;junit-1103.jar KTests.java   #compile
> java -cp .;junit-1103.jar KTests         #run tests

Correctly passing all tests will yield output similar to the following.

JUnit version 4.12
..........
Time: 0.024

OK (10 tests)

Failing some tests will yield long messages which hint at where there might be a problem. Failures always end with the number of tests passed/failed as in the following.

FAILURES!!!
Tests run: 10,  Failures: 5

6.2 Test Grading Policies

Some policies to keep in mind with respect to how automatic tests affect grades.

  • Credit on this section is proportional to the number of tests passed.
  • If there were 30 total tests for the project…
  • Passing 30 / 30 tests gets 30 / 30 * 50 = 50.00
  • Passing 15 / 30 tests gets 15 / 30 * 50 = 25.00
  • Passing 4 / 30 tests gets 4 / 30 * 50 = 6.67
  • A 5% penalty may be deducted from this portion if code does not compile initially but a grader is able to quickly fix the problem.
  • Passing no tests because code does not compile or does not work properly gets 0 credit.

7 Zip and Submit

7.1 Submit to Canvas

Once your are confident your code is working, you are ready to submit. Ensure your folder has all of the required files. Create a zip archive of your lab folder and submit it to blackboard.

On Canvas:

  • Click on the Assignments section
  • Click on the appropriate link for this lab
  • Scroll down to "Attach a File"
  • Click "Browse My Computer"
  • Select you Zip file and press OK

7.2 Late Policies

You may wish to review the policy on late project submission which will cost you late tokens to submit late or credit if you run out of tokens. No projects will be accepted more than 48 hours after the deadline.

http://www-users.cs.umn.edu/~kauffman/1103/syllabus.html#late-projects

8 Optional Problem: Calculate Exponentials

This is an optional problem for enrichment. It is not required but doing it earns only the pride of cracking a tough nut (i.e. no bonus credit).

A common use for computing is to produce numerical estimates which would otherwise be tedious and error-prone for humans to compute. The special mathematical constant e shows up often enough that it has computing functions specially designated for it: calling Math.exp(3.0) will produce e^3.0. It is possible that the CPU actually contains a circuit specially designed for this but it is also possible that the CPU only has instructions to do basic arithmetic (+,-,*,/). In that case, an algorithm must be used to compute e^3.0 which uses only these operators. Implementing such an algorithm is the subject of this problem.

e^x has a special identity associated with it which proves very useful for computational purposes. It is the following:

e^x = 1 + (x / 1!) + (x^2 / 2!) + (x^3 / 3!) + (x^4 / 4!) + ...
    = 1 + (x / 1)  + (x^2 / 2)  + (x^3 / 6)  + (x^4 / 24) + ...

This is an approximation which adds terms in a specific sequence to get better and better estimates for e. The notation 4! is "4 factorial" which is expands to

4! = 1 * 2 * 3 * 4

Similarly,

6! = 1 * 2 * 3 * 4 * 5 * 6

This suggests the following algorithm to compute e^3.0 which will add numbers on until we are satisfied with the accuracy.

  • Start with an estimate that is just 1.0
  • Calculate the next estimate by adding the first x term from the sequence. In our case x=3.0 so
    newEstimate = curEstimate + (3.0 / 1!)
                = 1.0 + (3.0 / 1)
                = 4.0
    

    This changes the estimate by 3.0, a pretty big change.

  • The curEstimate=4.0, add the next x term
    newEstimate = curEstimate + (3.0^2 / 2!)
                = 4.0 + (9.0 / 2)
                = 8.5
    

    A change of 4.5

  • The curEstimate=8.5, add the next x term
    newEstimate = curEstimate + (3.0^3 / 3!)
                = 8.5 + (27.0 / 6) = 8.5 + 4.5
                = 13.0
    

    A change of 4.5

  • The curEstimate=13.0, add the next x term
    newEstimate = curEstimate + (3.0^4 / 4!)
                = 13.0 + (81.0 / 24) = 13.0 + 3.375
                = 16.374
    

    A change of 3.375

Subsequently, the changes will gradually diminish until only tiny quantities are added on in additional iterations. At some point, the changes are small enough that a good approximation has been reached. This is often referred to as the tolerance of the approximation: how far off one is willing to tolerate from the true value of interest.

This problem translates the above approach into a numerical loop which will produce approximations for e^x.

8.1 Basic Approach

  • Prompt the user for their desired power of e using the prompt message
    Enter positive power of e (ex: 4.567):
    
  • Read the power using TextIO
  • Ensure there is a tolerance variable that is set to 1e-6 which is valid Java notation for 10^-6 of 0.000001. It will be used to check for loop termination.
  • Establish variables for other important quantities such as
    • the current estimate
    • the next estimate
    • the difference between current and next estimates
    • numerator and denominators from the formula
    • the iteration count
  • Enter a loop which checks whether the change between current and next estimates is above tolerance
  • Adjust the numerator and denominator variables as per the formula
  • Use the new values of numerator and denominator to create the next estimate by adding a term on to the current estimate
  • Compute the difference between current and next estimates
  • Print a message indicating the current iteration stats. Use printf() with the following format string:
    Iter %2d: e^%.2f = %16.8f (change %.8f)\n
    

    Substitute the iteration count, power, next estimate, and change into this format

  • Increase the iteration count and transfer value of the next estimate to the current estimate
  • When the loop completes print out the iteration count as in
    11 iterations to converge
    

    along with a message with the final estimate for e raised to the given power using the printf() and the format string

    e^%.2f = %16.8f\n
    

8.2 Demo

> javac EPow.java

> java EPow
Enter positive power of e (ex: 4.567):
1.0
Iter  1: e^1.00 =       2.00000000 (change 1.00000000)
Iter  2: e^1.00 =       2.50000000 (change 0.50000000)
Iter  3: e^1.00 =       2.66666667 (change 0.16666667)
Iter  4: e^1.00 =       2.70833333 (change 0.04166667)
Iter  5: e^1.00 =       2.71666667 (change 0.00833333)
Iter  6: e^1.00 =       2.71805556 (change 0.00138889)
Iter  7: e^1.00 =       2.71825397 (change 0.00019841)
Iter  8: e^1.00 =       2.71827877 (change 0.00002480)
Iter  9: e^1.00 =       2.71828153 (change 0.00000276)
Iter 10: e^1.00 =       2.71828180 (change 0.00000028)
11 iterations to converge
e^1.00 =       2.71828180

> java EPow
Enter positive power of e (ex: 4.567):
3
Iter  1: e^3.00 =       4.00000000 (change 3.00000000)
Iter  2: e^3.00 =       8.50000000 (change 4.50000000)
Iter  3: e^3.00 =      13.00000000 (change 4.50000000)
Iter  4: e^3.00 =      16.37500000 (change 3.37500000)
Iter  5: e^3.00 =      18.40000000 (change 2.02500000)
Iter  6: e^3.00 =      19.41250000 (change 1.01250000)
Iter  7: e^3.00 =      19.84642857 (change 0.43392857)
Iter  8: e^3.00 =      20.00915179 (change 0.16272321)
Iter  9: e^3.00 =      20.06339286 (change 0.05424107)
Iter 10: e^3.00 =      20.07966518 (change 0.01627232)
Iter 11: e^3.00 =      20.08410308 (change 0.00443791)
Iter 12: e^3.00 =      20.08521256 (change 0.00110948)
Iter 13: e^3.00 =      20.08546859 (change 0.00025603)
Iter 14: e^3.00 =      20.08552346 (change 0.00005486)
Iter 15: e^3.00 =      20.08553443 (change 0.00001097)
Iter 16: e^3.00 =      20.08553649 (change 0.00000206)
Iter 17: e^3.00 =      20.08553685 (change 0.00000036)
18 iterations to converge
e^3.00 =      20.08553685

> java EPow
Enter positive power of e (ex: 4.567):
0.3
Iter  1: e^0.30 =       1.30000000 (change 0.30000000)
Iter  2: e^0.30 =       1.34500000 (change 0.04500000)
Iter  3: e^0.30 =       1.34950000 (change 0.00450000)
Iter  4: e^0.30 =       1.34983750 (change 0.00033750)
Iter  5: e^0.30 =       1.34985775 (change 0.00002025)
Iter  6: e^0.30 =       1.34985876 (change 0.00000101)
Iter  7: e^0.30 =       1.34985881 (change 0.00000004)
8 iterations to converge
e^0.30 =       1.34985881

> java EPow
Enter positive power of e (ex: 4.567):
4.67
Iter  1: e^4.67 =       5.67000000 (change 4.67000000)
Iter  2: e^4.67 =      16.57445000 (change 10.90445000)
Iter  3: e^4.67 =      33.54904383 (change 16.97459383)
Iter  4: e^4.67 =      53.36688213 (change 19.81783830)
Iter  5: e^4.67 =      71.87674311 (change 18.50986097)
Iter  6: e^4.67 =      86.28358490 (change 14.40684179)
Iter  7: e^4.67 =      95.89500649 (change 9.61142159)
Iter  8: e^4.67 =     101.50567385 (change 5.61066736)
Iter  9: e^4.67 =     104.41698680 (change 2.91131295)
Iter 10: e^4.67 =     105.77656994 (change 1.35958315)
Iter 11: e^4.67 =     106.35377479 (change 0.57720485)
Iter 12: e^4.67 =     106.57840368 (change 0.22462889)
Iter 13: e^4.67 =     106.65909728 (change 0.08069361)
Iter 14: e^4.67 =     106.68601437 (change 0.02691708)
Iter 15: e^4.67 =     106.69439455 (change 0.00838018)
Iter 16: e^4.67 =     106.69684052 (change 0.00244597)
Iter 17: e^4.67 =     106.69751244 (change 0.00067192)
Iter 18: e^4.67 =     106.69768676 (change 0.00017433)
Iter 19: e^4.67 =     106.69772961 (change 0.00004285)
Iter 20: e^4.67 =     106.69773962 (change 0.00001000)
Iter 21: e^4.67 =     106.69774184 (change 0.00000222)
Iter 22: e^4.67 =     106.69774231 (change 0.00000047)
23 iterations to converge
e^4.67 =     106.69774231
>

Author: Chris Kauffman (kauffman@umn.edu)
Date: 2017-10-01 Sun 16:21