# Let's Stack Some Bricks

## Overview

This program is not likely to make you a Google-style billionaire, but it will serve to ramp up your practice from the small programs we have been writing in class. The computation we will perform doesn't even have a cool name like "The Sieve of Eratostheses" or "Fast QuickSort". It's just an excuse to glue some loops and conditionals together and to use some of the patterns we are learning to produce a cohesive larger program. So we will just call it "Stacking Some Bricks".

In this program you will combine the basic structures and patterns you have learned so far into a larger computation:

• prompt statement (user input)
• variable declarations
• data values and expressions
• assignment statement
• for loops
• conditional (if) statements
• Math object functions
• counter
• accumulator
• using the for loop index variable

That's a pile of stuff and you probably didn't even realize how much you have done until you saw it all in a list.

This program is also an opportunity to learn and practice a few new concepts. One is input data validation. You will be doing input data validation from now on in all your program assignments. Another is the process of programming. You will follow some disciplined and systematic construction practices that will make creating a correct program much easier than if you just went at it with no guidance or plan.

## Input

The user will first input a number "num", a positive integer. Then the user will then input "num" triples of numbers; these can be any real values.

For example, if the user first gives the integer "2" the program will then two times ask for 3 numbers (I am calling it a triple but you will use 3 separate prompts to get them). The user might give 126, 4, and 76.3 as the first triple. Then the program does it again to get the second set of 3 numbers; the user might give -3.4, -18, and 543.21 as the second set of 3 numbers.

You must validate the input values given to the program (see below). This means you must be sure the user gives input values that match what the program expects to be given.

## Output

Your program will print these results in the given order:

1. average of the maximums from each triple
2. largest of the minimums from the triples (I'll call it bigMin)
3. the largest individual value over all numbers (I'll call it bigMax)
4. the number of the triple bigMax was in
5. the count of how many inputs were negative
Truncate all numbers that are not integer to 3 decimal places.

For example, let's assume we got the input above from the user:

```  num    triple 1         triple 2
2      126, 4, 76.3     -3.4, -18, 543.21
```
The program prints 334.605 as the average of maximums, from ( 126 + 543.21 ) / 2
The program prints 4 as the largest of the minimums (larger of 4 and -18)
The program prints 543.21 as the largest of all the values
The program prints 2 as the triple containing the largest value
The program prints 2 as the count of how many values are negative

## Input Data Validation

Users make mistakes when typing input data. Your programs should be written to do something useful when that happens. Grinding to a halt and saying "urp..." is not particularly useful; neither is taking bad input data and just computing anyway, generating nutty and wrong results. Input validation is one aspect of making a program what we call "robust". A robust program resists crashing and works rationally in the face of errors or unexpected events.

First thing we need to do is detect when the input data is invalid. There are several things that can go wrong:

• When asked for a number within some range the user gives a number that fails to meet the requirements. For example, a positive integer is needed and the user types "-5".

• When asked for a number, the user gives a number that is formatted improperly. For example, an integer is needed and the user gives a floating point number like 13.716. You will find Math.floor and/or modular arithmetic (the % operator) useful in determining if a number is an integer or not.

• When asked for a number, the user types something that is not a number, such as "12dot79" or "go heels". The function "isNaN" will help here. For example,
```   isNaN("12dot79") evaluates to true.
```
This says "12dot79" is not-a-number. In fact, it is a string (text), and further, that string contains one or more characters that cannot appear in a correct number.
```   isNaN("12.734") evaluates to false.
```
This says that 12.734 is NOT not-a-number. It IS a number, meaning the string contains only characters that look like a proper number. The reverse sense of this logic can cause you some confusion, so just think it out slowly and get used to it.
```   isNaN(3.14159) evaluates to false.
```
This shows that isNaN can be called with a string argument or with an actual number argument. When called with an actual number (as here) it returns false (since a number is NOT not-a-number... that reverse logic sense again).

You will use conditional statements (if-then-else) to decide if the input values you get from a prompt statement meet all the requirements. If an input value fails to meet some requirement, the program must take some appropriate and useful action:

• you can report the error to the user and stop executing (return statement)

• you can report the error to the user and ask the user to try again to give good input (loop, usually while loop)

• you can try to make some intelligent repair and "manufacture" good input from the bad; if you do this, you should report to the user what value you decide to use. For example, if you ask for a positive integer and the user types "21.3657" you might truncate the value and report to the user that you are using "21" as the input value. Use this sparingly and only when you are sure the repairs are rational and acceptable.

## Test Data

Run your program on these test cases. Make sure your program produces the output indicated. Note the error cases at the end.

```--------------------------------------------------------------

input:  num   triples
3     (2,4.5,1) (300,7.1,21.3) (11,2,5)
output: avg max  bigMin   bigMax   triple    #negatives
105.166  7.1      300      2         0

explanation:
t1    t2    t3
maxs    4.5   300   11    105.166 is the average of these
mins    1     7.1   2     7.1 is the largest of these
bigMax  300 is in t2      it is the largest of the maxes
(and so the largest of all the numbers)
#negs   0                 as none are given

--------------------------------------------------------------

input:  num   triples
4     (-17,19.1,3.2) (1,-4,2) (8.3,21,101.02) (18.4,17.7,-13)
output: avg max   bigMin    bigMax    triple    #negatives
35.13     8.3       101.02    3         3

--------------------------------------------------------------

input:  num   triples
2     (11.3,-14,-1) (-100, 3.321, -12.2)
output: avg max   bigMin    bigMax    triple   #negatives
7.31      -14       11.3      1        4

--------------------------------------------------------------

input:  num
-3
output: error

--------------------------------------------------------------

input:  num
0
output: error

--------------------------------------------------------------

input:  num
6.5
output: error

--------------------------------------------------------------

input:  num
tarheels
output: error

--------------------------------------------------------------

input:  num   triples
2     ( 2, 3, four )
output: error

--------------------------------------------------------------
```

## Design Considerations

Think "for loop" for this program (since it's the only loop we know). The body of the loop will execute "num" times, where "num" is that first integer you get from the user. Each time through the loop, the body will do these things:

• get 3 new numbers from the user (3 prompt statements)
• find the largest of the 3 numbers and then accumulate that max into the sum needed to get the final average of max's
• find the smallest of the 3 numbers in this triple, and see if it is bigger than the current bigMin.
• check if any of the 3 numbers is greater than the current overall bigMax
• count any number that is negative

In the loop body, each time you get a new set of 3 numbers you will have to identify the largest and the smallest. To do this you can use conditional statements individually, or you may find Math.max and Math.min useful. You can google up their details, but basically they work like this:

```   Math.max(5,9) evaluates to 9
Math.min(3,7) evaluates to 3
Math.max(x,y) evaluates to the smaller of the values stored in
the variables x and y
```

No real surprises there. Well, one surprise. It might help to know you can give Math.min and Math.max as many arguments are you want... for example

```   Math.max(6,2,8,3,19,11,4) evaluates to 19
```

### Fun with min and max

Just for fun, note you can also find the max (min) of 3 numbers with nested function calls, this way:
• assume your 3 numbers are stored in variables a, b, and c
• the largest is given by the expression Math.max( a, Math.max(b,c) )

This first finds the larger of b and c, then takes that result and compares it to a. So the overall largest wins. This also extends to more than 3 values:

```   Math.max( Math.max(a,b), Math.max(c,d) )      4 numbers,
will work for any number of arguments that is a power of 2

Math.max( a, Math.max( b, Math.max(c,d) ) )   4 numbers
Math.max( a, Math.max( b, Math.max( c, Math.max(d,e) ) ) )   5 numbers

etc...
```
Here is an alternate formatting for 5 numbers, to help you see how an inner function call produces a value to be used as an argument for an outer function call. Remember, when function calls are "nested" like this, the parentheses tell the JavaScript interpreter to do the most deeply nested (inner) calls first, then work outward. You can think of the Math function call "turning into" the value it computes as a result:
```   Math.max( a,
Math.max( b,
Math.max( c,
Math.max(d,e)
)
)
)
```

This is all for your personal edification. These approaches work when your language has a Math.max that only takes 2 arguments. It also helps you better understand how to call functions like this and how to pass arguments for them to work on.

Try all this stuff in Bricks or JSFiddle, see how it works, experiment and learn. There is a whole world of programming fun out there for you to just reach out and grab onto !

## Notes on the Process of Programming

Although we often refer to the act of programming as "writing a program" it is not really like writing in the "term paper" or "blog entry" sense. You will not sit down, then type, type, type until you have a page or two, and then hold your nose and hope the compiler gives you a "like" when you try to execute it.

"Writing" a program is more like constructing a house. You should follow a step-by-step procedure and build your program small piece by small piece:

• In house construction, we first build a framework: we frame up the building. This gives a skeletal version of the building but with lots of finishing details missing. The overall shape and design, or architecture is evident, but the functionality of the final product is not there yet.
• After framing we "dry it in": we put on the sheathing, add the roof panels, put in the doors and windows, make it weather tight. In other words, we start fleshing out the framework with more of the structural components needed for strength and durability.
• After dry in, we begin the installation of the interior systems (HVAC, eletrical, plumbing, security). Each system is pressure tested or function tested as it is installed to make sure errors are fixed before the systems are buried in the drywall.
• After that, we call in the wallboard team, the finish carpenters, the painters, the flooring installers... and finally the county inspectors to give it the final OK for occupancy.

No analogy is perfect; I won't try to map your activities onto plumbers or carpet installers. However, there is good similarity here to the disciplined and systematic step-wise approach you should take in building your programs.

The primary principle to remember and follow is this:

Write 4 or 5 lines of code and then run it... test it...
make sure it is doing what you expect it to do before you add more code
Never write a big pile of code and hope for the best when you run it. It will have errors, and it will be difficult to determine which of the dozens of lines of code is the problem (or problems). Your "debugging" task will be time consuming and confusing. Instead, you take a working program, add 5 lines of code, and test it. If you find an error, then the error is most likely in one of the few lines you added.

This bring up the next principle:

Always have a working version of your program on hand;
build a new working version from that
When I say "working version", I mean a program that is syntactically correct, compiles and runs, and produces the output that you expect it to produce. It won't be doing everything the final version should do, but it is doing what you think it ought to be doing at this incomplete point. Let's say you have a working version, and you add a few lines of code... and it is suddenly hopelessly broken.... well, you can always just go back to that previous working version and "start over" without losing much time or wasting much effort. Just take out the few lines you added, rethink things, keep calm and carry on.

Begin construction with a basic (and simple) working version. It might do nothing but print "ok its working" but at least it is doing what you expect it to be doing. In keeping with our construction analogy we can call this the foundation. Then your grow your program towards the final functionality, adding one small piece of behavior at a time.

The next steps we can think of as "framing it up". Your new working version does not have to be much more than comments and alert statements. Identify the major chunks of activity the program must have and make a comment in place of each. Put in a few alert statements that announce something like "now doing the main processing loop" or "getting an integer from the user" and later you will replace those with real working code that make that activity actually happen. When you run this skeleton it will announce things in the right order and stop. It is not doing what the final version should do, but it is doing what you expect so it is a working verion.

Save that working version (so you can revert to it if the world goes all pear shaped), and now go on to make successive new working versions by adding the sheathing, roofing, windows, etc. one small chunk at a time. Each time you add a new chunk you have to make sure it is doing what you expect it to do. Then save that new working version and start another. Lather, rinse, repeat.

Each time you add a little code to build a new version you have the task of showing that it does what you expect it to do. And so, this brings up our next principle:

Test, test, test.    Then test.

In building a house we test the plumbing to see if it holds pressure before we bury the pipes in the drywall. In the same way, we test the code we write before we "bury" it in more code. Testing means thinking of all the different kinds of input the code could get and seeing if it responds the proper way to each kind. You should use lots of test cases, not just one or two. Try to work at the extremes of the ranges of values the data can have. Then work beyond the extremes...see if your code can handle the bad data robustly.

Does the code expect integers from 1 to 100? Then try 1, and 100, and 2 and 99... and then 0, -1, 101, ... then some in the middle of the range. Then try some numbers that are not integers. Then try some input that is not even numeric.

I am using "input" as a generic term here. As you add code to your program you will often be creating "fake" input to test parts that are not directly receiving values from the user. Eventually you will grow the program to the point where it is using user-supplied values.

Be liberal in your use of alerts to see what variable values are when you are trying to figure out if your new code is working correctly. You can always take them out (or comment them out) when you are happy with what the code is computing.

### Divide and Conquer

Once you have the skeleton framed up, you have to decide what to work on first to flesh it out. There is no one way to do this... you might want to work on the easy parts first and get something working quickly as an encouragement to keep on going. Overall, this approach is called "divide and conquer". Rather than see the program as one big problem to solve, we make progress by breaking it into a bunch of smaller problems. We solve the smaller problems one by one and compose those small solutions into a big problem solution. For this program, here are some considerations.

Validation first? Last?

One common thing to do is work on the functionality assuming the input values are good (you assume that when you test you are able to type in correct input values... we will not make that assumption for the general user however). Once the program is producing correct output for correct input, you then go back and add code to do input validation.

Others prefer to do the input validation code first. The "functionality" of the program would consist of nothing other that echoing the input data to the output, or printing error messages if the input is bad. Once the program properly passes on (prints out) good inputs and weeds out bad ones, you can go in and add code to compute real results with the good inputs.

Loop body with partial functionality

For this program you will be doing several different things inside the loop body with each triple. You will be finding max and min. You will be accumulating max's for the final average. You will be checking min to see if its a new bigMin. You will be counting negative inputs... etc. One thing you can do to build in small pieces is not work on all those things at once. Try building a program that does nothing but take the user input triples and count the negative ones. After the loop completes print out that count.

Now you have a working version that does one of the many things you are supposed to compute, and a loop is part of that structure. Go back and create the next working version by adding to the loop body the parts that find max's, and compute the average after the loop. Then add another function... and so on.