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

   READ(*,InputFormat)  Number, (Data(i), i=1, Number)
   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
Click here to download this program.

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.