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)
Click here to download this program.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
The output of the program is: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
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
This is the format used to print a line of the histogram.(1X, I5, A,35A, A, I2, A) <--------->^^<----------> Part1 || Part2 || +----- from Repetition
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