# Print a Histogram

### Problem Statement

Suppose we have an input of the following form. The first line gives the number of integers that follow. On each of the subsequent input lines, there are five integers in the form of 5I5, except for the last line which could have fewer than five integers.
```         1    1    2    2
....5....0....5....0....5
22
8    23   27   24   40
45   43   38   26   16
8    8    6    3    5
4    0    2    0    1
2    1
```

Write a Fortran program that reads in these numbers and for each integer prints that many number of asterisks on the same line followed by the value of that integer. The following is the desired output:

```         1    1    2    2    3    3    4    4    5    5    6
....5....0....5....0....5....0....5....0....5....0....5....0
8 |******** ( 8)
23 |*********************** (23)
27 |*************************** (27)
24 |************************ (24)
40 |**************************************** (40)
45 |********************************************* (45)
43 |******************************************* (43)
38 |************************************** (38)
26 |************************** (26)
16 |**************** (16)
8 |******** ( 8)
8 |******** ( 8)
6 |****** ( 6)
3 |*** ( 3)
5 |***** ( 5)
4 |**** ( 4)
0 | ( 0)
2 |** ( 2)
0 | ( 0)
1 |* ( 1)
2 |** ( 2)
1 |* ( 1)
```

### Solution

```PROGRAM  VerticalBarChart
IMPLICIT  NONE
CHARACTER(LEN=*), PARAMETER  :: Part1 = "(1X, I5, A,"
CHARACTER(LEN=*), PARAMETER  :: Part2 = "A, A, I2, A)"
CHARACTER(LEN=2)             :: Repetition
CHARACTER(LEN=10), PARAMETER :: InputFormat = "(I5/(5I5))"
INTEGER                      :: Number, i, j
INTEGER, DIMENSION(1:100)    :: Data

DO i = 1, Number
IF (Data(i) /= 0) THEN
WRITE(Repetition,"(I2)")  Data(i)
WRITE(*,Part1 // Repetition // Part2)  Data(i), " |", ("*", j=1,Data(i)), " (", Data(i), ")"
ELSE
WRITE(*,"(1X, I5, A, I2, A)")  Data(i), " | (", Data(i), ")"
END IF
END DO
END PROGRAM  VerticalBarChart
```

### Program Input and Output

Suppose the input data consist of the following:
```         1    1    2    2
....5....0....5....0....5
22
8    23   27   24   40
45   43   38   26   16
8    8    6    3    5
4    0    2    0    1
2    1
```
The output of the program is:
```         1    1    2    2    3    3    4    4    5    5    6
....5....0....5....0....5....0....5....0....5....0....5....0
8 |******** ( 8)
23 |*********************** (23)
27 |*************************** (27)
24 |************************ (24)
40 |**************************************** (40)
45 |********************************************* (45)
43 |******************************************* (43)
38 |************************************** (38)
26 |************************** (26)
16 |**************** (16)
8 |******** ( 8)
8 |******** ( 8)
6 |****** ( 6)
3 |*** ( 3)
5 |***** ( 5)
4 |**** ( 4)
0 | ( 0)
2 |** ( 2)
0 | ( 0)
1 |* ( 1)
2 |** ( 2)
1 |* ( 1)
```

### Discussion

At a first glance, you may have an impression that this is an easy program. But, in fact, it is not the case if you do not know internal files. This is the first nontrivial use of internal file. So, read it carefully.
• This wrong impression may come from the following analysis. Since we need a space for printer control, 1X must be the first edit descriptor. Correct! This is followed by an integer and a vertical bar which can be printed using the A edit descriptor. Correct again! Now suppose we need to print n asterisks. We could use a repetition indicator like the following:
```(1X, I5, A, ??A ...)
```
A ?? is used for the repetition indicator because it depends on the value of n. More precisely, if n is 15, ?? should be 15; if n is 34, then ?? should be 34; and so on. So far so good.

Then, (, an integer and ) can be printed using A, I2 and A. So, we are done and the following is our format:

```(1X, I5, A, ??A, A, I2, A)
```
• What is the value for ??, especially it is different from time to time? This is the difficult part. We can use internal file to achieve this. Since ?? is the only missing part and the other parts are always fixed, we can store them into two CHARACTER variables:
```CHARACTER(LEN=*), PARAMETER  :: Part1 = "(1X, I5, A,"
CHARACTER(LEN=*), PARAMETER  :: Part2 = "A, A, I2, A)"
```
If we know the value of n, we can write it to a CHARACTER variable of length 2:
```CHARACTER(LEN=2) :: Repetition

WRITE(Repetition,"(I2)")  n
```
Thus, if the value of n is 35, after this WRITE, CHARACTER variable Repetition contains "35". Now, we have the the missing part and a simple concatenation would construct a correct format for us:
```Part1 // Repetition // Part2
```
Continue with the above example. If n is 35, then Repetition is "35" and the above concatenation gives:
```(1X, I5, A,35A, A, I2, A)
<--------->^^<---------->
Part1   ||    Part2
||
+----- from Repetition
```
This is the format used to print a line of the histogram.
• Wait a minute, why couldn't use
```Part1 // n // Part2
```
This will insert the value of n between Part1 and Part2! Unfortunately, this is incorrect because the concatenation operator // can only use CHARACTER values. As a result, the value of n must be converted to a character string and this is why we use an internal file WRITE.
• The remaining of this program is simple. The input data values are read into array Data(). For each entry Data(i), if its value is non-zero, we convert the value of Data(i) to a character string and store it in Repetition. Then, a concatenation is used to construct the desired format. However, if Data(i) is zero, we just use a simple format because we do not need the ??A for printing asterisks.