o CISC 3115 — Lab #1

CISC 1115
Introduction to Modern Programming Techniques
Lab #01
Classes

How to Develop and Submit your Labs

Lab 1.1 An Upper-Bounded Counter

The following two exercises implement a counter that can only be incremented to a specified limit. The first exercise (1.1.1) implements the object class, and the second (1.1.2) the app class

What's the Point of This Lab?

Lab 1.1.1 An Upper-Bounded Counter Class (UpperBoundedCounter) (Approval)

Write a class UpperBouncedCounter that models an up/down counter with an upper limit. The counter can always be decremented, but can only be incremented as long as the current value is less then the limit.

The class should contain the following state and behavior:

  • Two integer instance variables: value and limit
  • Two constructors:
    • A 2-arg constructor that accepts an initial value and an upper limit (in that order)
    • A 1-arg constructor that accepts an upper limit and iniitalizes the value to 0
    You must leverage the 2-arg constructor when defining the 1-arg
  • getter methods for the two instance variables
  • boolean-valued up and down methods. The methods return true if the operation could be performed and false otherwise.
  • A toString method that prints the value and limit in the format value/limit
  • A read method that accepts a Scanner, reads in an initial value and a limit (in that order), and returns a new UpperBoundedCounter object constructed from those values
  • Do not include a main method (that's the next exercise)

The next lab (1.1.2) illustrates the object in use; you might want to take a look at it before you start implementing your class.

What's the Point of This Lab?
  • Has you implement a class containing most of the standard methods that are usually coded into a class: constructors, low-level (getters), high-level (up/down), toString
  • The semantics of a upper-bounded counter are somewhat similar to that of a bank account with overdraft (can add and subtract from a primary value, and you can't go beyond some limit in both cases), so the basics of this should be familiar..

Lab 1.1.2 An App Class for 1.1.1 (UpperBoundedCounterApp) (Approval)

Write an app class containing a main method (and any other supporting methods you want) that illustrates the use of your class from Lab 1.1.1. The app should:
  • read in an object of the class from the file counter_actions.text, and print its value
  • read in actions from the same file; acceptable actions are + for an up and - for a down.
    • print out the actions the return value from the method call, and the new value of the object after calling the proper method
  • create a second object, with an initial value equal to one more than the value of the first object, and a limit of twice the limit of the first object; print out this newly created object
  • bump up the second object to it limit, then bump it down to the value of the first object, printing out the object each step of the way

Here is a sample set of data:

counter_actions.text

0 5
+
+
+
+
+
+
-
-
-
+
+
+
Sample Test Run

Here is a sample execution of the program.
User input is in bold. Your program should replicate the prompts and output:

After reading in ubc1: 0/5
Action is + ... up: true ... ubc1: 1/5
Action is + ... up: true ... ubc1: 2/5
Action is + ... up: true ... ubc1: 3/5
Action is + ... up: true ... ubc1: 4/5
Action is + ... up: true ... ubc1: 5/5
Action is + ... up: false ... ubc1: 5/5
Action is - ... down: true ... ubc1: 4/5
Action is - ... down: true ... ubc1: 3/5
Action is - ... down: true ... ubc1: 2/5
Action is + ... up: true ... ubc1: 3/5
Action is + ... up: true ... ubc1: 4/5
Action is + ... up: true ... ubc1: 5/5

Creating ubc2 with a value one more than ubc1's value and a limit twice that of ubc1's limit
Initially: ubc2: 6/10
Bumping ubc2 up to its limit
After an up: ubc2: 7/10
After an up: ubc2: 8/10
After an up: ubc2: 9/10
After an up: ubc2: 10/10
... and now down to ubc1's value
After a down: ubc2: 9/10
After a down: ubc2: 8/10
After a down: ubc2: 7/10
After a down: ubc2: 6/10
After a down: ubc2: 5/10

Here is the actual output from System.out (stdout or the standard output stream) as you will see in in CodeLab's test case tables. stdout

After reading in ubc1: 0/5
Action is + ... up: true ... ubc1: 1/5
Action is + ... up: true ... ubc1: 2/5
Action is + ... up: true ... ubc1: 3/5
Action is + ... up: true ... ubc1: 4/5
Action is + ... up: true ... ubc1: 5/5
Action is + ... up: false ... ubc1: 5/5
Action is - ... down: true ... ubc1: 4/5
Action is - ... down: true ... ubc1: 3/5
Action is - ... down: true ... ubc1: 2/5
Action is + ... up: true ... ubc1: 3/5
Action is + ... up: true ... ubc1: 4/5
Action is + ... up: true ... ubc1: 5/5

Creating ubc2 with a value one more than ubc1's value and a limit twice that of ubc1's limit
Initially: ubc2: 6/10
Bumping ubc2 up to its limit
After an up: ubc2: 7/10
After an up: ubc2: 8/10
After an up: ubc2: 9/10
After an up: ubc2: 10/10
... and now down to ubc1's value
After a down: ubc2: 9/10
After a down: ubc2: 8/10
After a down: ubc2: 7/10
After a down: ubc2: 6/10
After a down: ubc2: 5/10

What's the Point of This Lab?
  • Practice writing an app class illustrating use of an object
  • Processing file data
    • uses the read method of the class
    • reads in an interprets actions on the object
      • we'll be using this model for some of our other examples
  • Reading and interpreting Codelab's feedback and understanding System.out output for an interactive program.
    • 'Hopefully' (😀), you will have an 'error' in your output, i.e., your output will not match the 'correct' (i.e. mine) exactly. The way to deal with this (ignoring the 'Ask Your Teacher' route) is to go down to the 'Test Case Table' in the 'Result' tab and particularly if your looking at System.out or file output, click the 'More Information' link. The Lab page (on the main course page) has a description on how to read the string comparison; once you get the basic idea it can be very helpful.

Lab 1.2 — An RGB Color Class

Lab 1.2.1 — An RGB Color Class (Color)

Write a class, named Color, that supports RGB (red-green-blue) color values. RGB color values consist of three integers values (for the red, green, and blue primary values) each in the range of 0 … 255, with 0 being an absence of the corresponding primary, and 255 being full saturation.

Being that 255 is FF in hexadecimal, colors are often saintly representing as a six digit hex value, e.g. #000000 (for black — no color), or #ff0000 (for red — full red, no green or black).

The class supports the following state and behavior:

As with the previous pair of exercises, see Lab 1.2.2 for the sample output of the illustrative app

Lab 1.2.2 — An RGB Color App Class (ColorApp))

Write the app class for Lab 1.2.1
  • Below is sample output for the app

What's the Point of This Lab?

color.data

0 0 0
0 0 255
0 255 0
0 255 255
255 0 0 
255 0 255
255 255 0
255 255 255
10 20 30
Sample Test Run

Here is a sample execution of the program.
User input is in bold. Your program should replicate the prompts and output:

r: 0 g: 0 b: 0
is valid: true
hex: #000000
name: Black
is grey: true
is primary: false

r: 0 g: 0 b: 255
is valid: true
hex: #0000ff
name: Blue
is grey: false
is primary: true

r: 0 g: 255 b: 0
is valid: true
hex: #00ff00
name: Green
is grey: false
is primary: true

r: 0 g: 255 b: 255
is valid: true
hex: #00ffff
name: Aqua
is grey: false
is primary: false

r: 255 g: 0 b: 0
is valid: true
hex: #ff0000
name: Red
is grey: false
is primary: true

r: 255 g: 0 b: 255
is valid: true
hex: #ff00ff
name: Magenta
is grey: false
is primary: false

r: 255 g: 255 b: 0
is valid: true
hex: #ffff00
name: Yellow
is grey: false
is primary: false

r: 255 g: 255 b: 255
is valid: true
hex: #ffffff
name: White
is grey: true
is primary: false

r: 10 g: 20 b: 30
is valid: true
hex: #0a141e
name: Unknown color (#0a141e)
is grey: false
is primary: false

r: 0 g: 0 b: 0
is valid: true
hex: #000000
name: Black
is grey: true
is primary: false

r: 0 g: 0 b: 255
is valid: true
hex: #0000ff
name: Blue
is grey: false
is primary: true

r: 0 g: 255 b: 0
is valid: true
hex: #00ff00
name: Green
is grey: false
is primary: true

r: 0 g: 255 b: 255
is valid: true
hex: #00ffff
name: Aqua
is grey: false
is primary: false

r: 255 g: 0 b: 0
is valid: true
hex: #ff0000
name: Red
is grey: false
is primary: true

r: 255 g: 0 b: 255
is valid: true
hex: #ff00ff
name: Magenta
is grey: false
is primary: false

r: 255 g: 255 b: 0
is valid: true
hex: #ffff00
name: Yellow
is grey: false
is primary: false

r: 255 g: 255 b: 255
is valid: true
hex: #ffffff
name: White
is grey: true
is primary: false

r: 10 g: 20 b: 30
is valid: true
hex: #0a141e
name: Unknown color (#0a141e)
is grey: false
is primary: false

 === Printing out the pre-defined Color objects

BLACK: (0, 0, 0)
WHITE: (255, 255, 255)
RED: (255, 0, 0)
GREEN: (0, 255, 0)
BLUE: (0, 0, 255)

What's the Point of This Lab?

Lab 1.3 Quadrilateral

Lab 1.3.1 — Quadrilateralsl Class (Quadrilateral) (Approval)

Model a quadirilateral (four sided figure) in 2-dimensional space (i.e., the 2D plane). Like the LinePair, a quadrilateral is represented as four pair of values, but here they represent the found corners of the figure, consisting of four lines:
      (x1, y1) (point 1)             (x2, y2) (point 2)
               ______________________ 
               \                    /
                \                  /
                 \________________/        
         (x4, y4) (point 4)         (x3, y3) (point 3)

(Note the order of the points; that is the order in which they are input)

The class should contain the following:

  • four (4) Point instance variables corresponding to the four points displayed above
  • a 4-arg constructor, corresponding to the points
  • liesInOneQuadrant, that returns true if the quadrilateral is completely contained within a single quadrant (i.e., all four points are inthe sme quadrant).
  • isParallelogram: returns true of the quadrilateral is a parallelogram, i.e., opposite sides are equal
  • isRhombus: returns true if the quadrilateral is a rhombus, i.e., all four sides are equal
  • toString it should be the concatenation of the toString of the four Point instance variables in the proper order.

I've supplied the Line and Point classes (both as source and class files; you might want to experiment with your IDE in how to add .class files to your project.

Notes
  • a quadrilateral can be thought of as four points (the 'corners') or four lines (the sides). (There are other possibilities, but these two are the simplest). You thus have two 'natural' choices for instance variables:
    • four Points
    • four Lines
    For this exercise, I'm going to ask you to represent the quadrilateral as four Point objects (we discussed this in class).
  • Your constructor(s): Your constructor should consist of the four Points.
  • The app is printing out quadrant info, which comes from the Point class … you have that from your instance variables
  • The class' isRhombus amd isParallelogram methods require the length of the various sides, and length is a method of the Line class. You have a couple of options to get that from your four Point instance variables:
    • add four additional instance variables, side1 of type line, side2, etc (you can initialize them in the constructor together with the four Point instance variables (not recommended, don't need the Line objects as instance variables; it's redundant.
    • create the four sides (again, they're Line objects) in the above two method (i.e., when and where you need them).
    You can then call the length method on the sides under being looked at.
  • Note isParallelogram could also be defined by leveraging Line's slope method but would either fail, or require special logic for the case of vetical sides (which have undefined slope). (After you get your class working, you might want to try using slope instead; it may give you a chance to become a bit familiar with Java's NaN (not-a-number) value.)
  • Lab 1.3.2 — Quadrilateral App Class (QuadrilateralApp) (Approval)

    Code the app class for Lab 1.3.1

    quadrilateral.data

    1 1   2 1   2 2   1 2	 
    1 -1   1 1  -2 1  -2 -1 
    0 0   1 0   1 1   0 2
     
    Sample Test Run

    Here is a sample execution of the program.
    User input is in bold. Your program should replicate the prompts and output:

    (1, 1) - (2, 1) / (2, 2) - (1, 2)
    (1, 1) Quadrant: Quadrant 1 (1)
    (2, 1) Quadrant: Quadrant 1 (1)
    (2, 2) Quadrant: Quadrant 1 (1)
    (1, 2) Quadrant: Quadrant 1 (1)
    Quadrilateral lies in one quadrant: true
    Rhombus

    (1, -1) - (1, 1) / (-2, 1) - (-2, -1)
    (1, -1) Quadrant: Quadrant 4 (4)
    (1, 1) Quadrant: Quadrant 1 (1)
    (-2, 1) Quadrant: Quadrant 2 (2)
    (-2, -1) Quadrant: Quadrant 3 (3)
    Quadrilateral lies in one quadrant: false
    Parallelogram

    (0, 0) - (1, 0) / (1, 1) - (0, 2)
    (0, 0) Quadrant: Origin (0)
    (1, 0) Quadrant: Positive x axis (5)
    (1, 1) Quadrant: Quadrant 1 (1)
    (0, 2) Quadrant: Positive y axis (6)
    Quadrilateral lies in one quadrant: false
    Simple quadrilateral

    stdout

    (1, 1) - (2, 1) / (2, 2) - (1, 2)
    (1, 1) Quadrant: Quadrant 1 (1)
    (2, 1) Quadrant: Quadrant 1 (1)
    (2, 2) Quadrant: Quadrant 1 (1)
    (1, 2) Quadrant: Quadrant 1 (1)
    Quadrilateral lies in one quadrant: true
    Rhombus
    
    (1, -1) - (1, 1) / (-2, 1) - (-2, -1)
    (1, -1) Quadrant: Quadrant 4 (4)
    (1, 1) Quadrant: Quadrant 1 (1)
    (-2, 1) Quadrant: Quadrant 2 (2)
    (-2, -1) Quadrant: Quadrant 3 (3)
    Quadrilateral lies in one quadrant: false
    Parallelogram
    
    (0, 0) - (1, 0) / (1, 1) - (0, 2)
    (0, 0) Quadrant: Origin (0)
    (1, 0) Quadrant: Positive x axis (5)
    (1, 1) Quadrant: Quadrant 1 (1)
    (0, 2) Quadrant: Positive y axis (6)
    Quadrilateral lies in one quadrant: false
    Simple quadrilateral
    
     

    What's the Point of This Lab?
    • First use of composition: objects as instance variables of other objects
    • Interesting issues in the decision as to what sort of instance variables to use — Lines or Points
    • Some more advanced work with your IDE (using third party classes in your project)

    Lab 1.4 — Phonebook (Phonebook) (Approval)

    Lab 1.4.1 — The Phonebook Class (Phonebook)

    Make the following changes to the Phonebook class of Lecture 4:

    Lab 1.4.2 — Phonebook App (PhonebookApp) (Approval)

    Write the app for Lab 1.2.1. (I've supplied the PhonebookEntry class source file as well the Phonebook file).
    • The format of the entries in the file should be:
      last-name   first-name   phone-number
      		
    • The lookup process now prompts for both a last and a first name
    • Since the user at the keyboard now has a choice of lookup (normal or reverse), we first prompt for the choice before entering the data used for the search.
    • Rather than continuing until the user signals end-of-file (at the keyboard) as in the lecture version, the user enters a 'q' as their choice to indicate they are done
    • After the user is done, the number of lookups and reverse lookups performed are printed
    • Finally, sort the array by last name / first name and write the results to the file sorted.text
    Remember, the search data is entered from the keyboard.

    stdin

    l
    Arnow
    David
    r
    456-789-0123
    l
    Weiss
    Jerrold
    l
    Weiss
    Gerald
    r 
    111-123-4567
    q
    

    phonebook.text

    Arnow       David    123-456-7890
    Harrow      Keith    234-567-8901
    Jones       Jackie   345-678-9012
    Augenstein  Moshe    456-789-0123
    Sokol       Dina     567-890-1234
    Tenenbaum   Aaron    678-901-2345
    Weiss       Gerald   789-012-3456
    Cox         Jim      890-123-4567
    Langsam     Yedidyah 901-234-5678
    Thurm       Joseph   012-345-6789
    
    Sample Test Run

    Here is a sample execution of the program.
    User input is in bold. Your program should replicate the prompts and output:

    lookup, reverse-lookup, quit (l/r/q)? l
    last name? Arnow
    firt name? David
    David Arnow's phone number is 123-456-7890

    lookup, reverse-lookup, quit (l/r/q)? r
    phone number (nnn-nnn-nnnn)? 456-789-0123
    456-789-0123 belongs to Augenstein, Moshe

    lookup, reverse-lookup, quit (l/r/q)? l
    last name? Weiss
    first name? Jerrold
    - - Name not found

    lookup, reverse-lookup, quit (l/r/q)? l
    last name? Weiss
    first name? Gerald
    Gerald Weiss's phone number is 789-012-3456

    lookup, reverse-lookup, quit (l/r/q)? r
    phone number (nnn-nnn-nnnn)? 111-123-4567
    -- Phone number not found

    lookup, reverse-lookup, quit (l/r/q)? q

    3 lookups performed
    2 reverse lookups performed

    stdout

    lookup, reverse-lookup, quit (l/r/q)? last name? first name? David Arnow's phone number is 123-456-7890
    
    lookup, reverse-lookup, quit (l/r/q)? phone number (nnn-nnn-nnnn)? 456-789-0123 belongs to Augenstein, Moshe
    
    lookup, reverse-lookup, quit (l/r/q)? last name? first name? -- Name not found
    
    lookup, reverse-lookup, quit (l/r/q)? last name? first name? Gerald Weiss's phone number is 789-012-3456
    
    lookup, reverse-lookup, quit (l/r/q)? phone number (nnn-nnn-nnnn)? -- Phone number not found
    
    lookup, reverse-lookup, quit (l/r/q)? 
    3 lookups performed
    2 reverse lookups performed
    
    sorted.text
    Arnow David 123-456-7890
    Augenstein Moshe 456-789-0123
    Cox Jim 890-123-4567
    Harrow Keith 234-567-8901
    Jones Jackie 345-678-9012
    Langsam Yedidyah 901-234-5678
    Sokol Dina 567-890-1234
    Tenenbaum Aaron 678-901-2345
    Thurm Joseph 012-345-6789
    Weiss Gerald 789-012-3456
    

    What's the Point of This Lab?
      • Like all the other apps in this, this one builds on the corresponding app in the lecture
      • Familiarizing yourself with these apps will make it easier for you to understand class implementations
      • This phone book app will be one of the app themes running through the semester
      • Sorting class objects

    Lab 1.5 — A Container

    Lab 1.5.1 — A Container (Container) (Approval)

    Starting with the Container class from Lecture 4: and add the following methods:

    input file

    A 	dog	
    A 	cat
    F 	cat
    F 	cow
    F 	dog
    C	cat
    C	cow
    G	1
    G	0
    S	1	cow
    F 	cow
    F	cat
    
    
    Sample Test Run

    Here is a sample execution of the program.
    User input is in bold. Your program should replicate the prompts and output:

    After adding dog: {dog}
    After adding cat: {dog, cat}
    cat is at position 1 of the container
    cow is not in the container
    dog is at position 0 of the container
    cat is in the container
    cow is not in the container
    The value at location 1 is cat
    The value at location 0 is dog
    After setting position 1 to cow: {dog, cow}
    cow is at position 1 of the container
    cat is not in the container

    stdout

    After adding dog: {dog}
    After adding cat: {dog, cat}
    cat is at position 1 of the container
    cow is not in the container
    dog is at position 0 of the container
    cat is in the container
    cow is not in the container
    The value at location 1 is cat
    The value at location 0 is dog
    After setting position 1 to cow: {dog, cow}
    cow is at position 1 of the container
    cat is not in the container
    

    What's the Point of This Lab?
    • Practice making changes to someone else's existing class.
    • Introduce you to thinking about and coding delegation methods.
      • If you get completely stuck on writing contains using find (as opposed to recoding the search logic, or don't even understand what you're being asked to do, go look at my Lecture 12 (Techniques III) notes -- look for (Linear) Searching an Array; it shows you what I want. (But please give it some thought first.
        • The technique is called leveraging there; we'll dicuss these terms in more detail in class.

    Lab 1.5.2 — A Container Class App (ContainerApp))

    Write the app class for Lab 1.5.1

    What's the Point of This Lab?
    • There's a static (class) variable in this class (CAPACITY)
    • A slightly more involved toString
    • Leveraging find to get contains

    Labs 1.6 & 1.7 — Immutable and Mutable Classes

    What's the Point of This Lab?
    • Practice writing an immutable as well as a muable class.
    • Writing a pair class
    • Overloaded constructors, and in particular the this() construct in constructors.

    The integer classes implemented in this lab are for all practical purposes useless, the primitive int type provides the same operations, and in a much more intuitive fashion. We introduce them for several reasons:

    Lab 1.6 Immutable Integer

    Lab 1.6.1 An Immutable Integer Class (ImmutableInt) (Approval)

    Write an immutable class, Immutable, modelling integers, with the following state/behavior:
    • Methods:
      • ImmutableInt add(ImmutableInt immutableInt)
      • ImmutableInt sub(ImmutableInt immutableInt)
      • ImmutableInt mul(ImmutableInt immutableInt)
      • ImmutableInt div(ImmutableInt immutableInt)
      • toString()
    • State:
      • An int instance variable maintaining the integer value of the object

    • Have an overloaded, 0-argument constructor that assigns 0 to the internal state variable. This constructor should leverage the 1-argument constructor *i.e., use the this(…) construct)
    • You can see the output below of the corresponding app class.
    • Assume 0 is never sent as the argument to div
    • The app consists of various declarations and creations of the objects, and calls to the methods; e.g.:
      …
      ImmutableInt i1 = new ImmutableInt(10);
      System.out.println("i1: " + i1);
      …
      System.out.println("i1.add(i2): " + i1.add(i2);
      …
      		
      • Part of the challenge (i.e., 'fun') here is trying to reproduce my app (i.e., the declaration and creation of the reference variables and objects, and the various calls to the methods of the class. Please feel free to query me if you are having trouble doing so … I will be happy to give you hints

    stdout

    i1: 10
    i2: 20
    i3: 0
    
    i1.add(i2): 30
    i1.sub(i2): -10
    i1.mul(i2): 200
    i1.div(i2): 0
    
    i1: 10
    i2: 20
    i3: 0
    

    Lab 1.6.2 An App Class for 1.6.1 (ImmutableIntApp) (Approval)

    Write the app class for lab 1.6.1. The output should match the output as shown in that exercise.

    What's the Point of This Lab?

    Lab 1.7 Mutable Integer

    Lab 1.7.1 A Mutable Integer Class (MutableInt) (Approval)

    Write a Mutable class, MutableInt, modelling integers,with the following state/behavior:
    • Methods:
      • MutableInt increaseBy(MutableInt immutableInt)
      • MutableInt decreaseBy(MutableInt immutableInt)
      • MutableInt multiplyBy(MutableInt immutableInt)
      • MutableInt divideBy(MutableInt immutableInt)
      • MutableInt reset()
      • toString()
    • State:
      • An int instance variable maintaining the integer value of the object

    • Have an overloaded, 0-argument constructor that assigns 0 to the internal state variable. This constructor should leverage the 1-argument constructor *i.e., use the this(…) construct)
    • reset sets the internal state variable to 0
    • Again, the output of the corresponding app class is shown below.
    • Assume 0 is never sent as the argument to divideBy
    • The semantics of the method should be that the receiver is returned as the value of the method, allowing for operation chaining
    • As in the previous exercise, The app consists of various declarations and creations of the objects, and calls to the methods; e.g.:
      …
      MutableInt i0 = new MutableInt();
      System.out.println("i0: " + i0);
      …
      System.out.println("i0.increaseBy(i1): " + i0.increaseBy(i1);
      …
      		
      • Again, part of the challenge (i.e., 'fun') here is trying to reproduce my app (i.e., the declaration and creation of the reference variables and objects, and the various calls to the methods of the class. Please feel free to query me if you are having trouble doing so … I will be happy to give you hints
        • I'm guessing this one is a bit more 'challenging'' then the previous, but once you get here, you'll have the experience of the first one, which should be a help.

    stdout

    ===== Initial Values =====
    i0: 0
    i1: 10
    i2: 5
    i3: 20
    i4: 25
    
    i0.increaseBy(i1): 10
    i0: 10
    i1: 10
    i2: 5
    i3: 20
    i4: 25
    
    i0.decreaseBy(i2): 5
    i0: 5
    i1: 10
    i2: 5
    i3: 20
    i4: 25
    
    i0.multiplyBy(i3): 100
    i0: 100
    i1: 10
    i2: 5
    i3: 20
    i4: 25
    
    i0.divideBy(i4): 4
    i0: 4
    i1: 10
    i2: 5
    i3: 20
    i4: 25
    
    i0.reset(): 0
    i0: 0
    
    ===== Chaining =====
    
    i0.increaseBy(i1).decreaseBy(i2).multiplyBy(i3).divideBy(i4): 4
    i0: 4
    i1: 10
    i2: 5
    i3: 20
    i4: 25
    
    

    Lab 1.7.2 An App Class for 1.7.1 (ImmutableIntApp) (Approval)

    Write the app class for lab 1.7.1/ The output should match the output as shown in that exercise.

    What's the Point of This Lab?
    • A fairly simple, baseline example of a mutable class