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)
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.
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)
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.(1X, I5, A, ??A ...)
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)
If we know the value of n, we can write it to a CHARACTER variable of length 2:CHARACTER(LEN=*), PARAMETER :: Part1 = "(1X, I5, A," CHARACTER(LEN=*), PARAMETER :: Part2 = "A, A, I2, A)"
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:CHARACTER(LEN=2) :: Repetition WRITE(Repetition,"(I2)") n
Continue with the above example. If n is 35, then Repetition is "35" and the above concatenation gives:Part1 // Repetition // Part2
(1X, I5, A,35A, A, I2, A)
<--------->^^<---------->
Part1 || Part2
||
+----- from Repetition
This is the format used to print a line of the histogram.
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.Part1 // n // Part2