PROGRAM Frequency_Distribution_2
!-----------------------------------------------------------------------
! Program to generate a bar graph of the number of 1-hour periods in
! which there were 0, 1, 2, ... defective parts produced by a machine.
! The data is read from a file.  Identifiers used are:
!     MaxDefective : parameter representing maximum # of defective
!                    parts
!     Count        : Count(I) = # of 1-hour periods with I defective
!                    parts
!     NumDefects   : number of defective parts read from file
!     FileName     : name of the data file
!     End_of_File  : end-of-file indicator
!     DrawBarGraph : subroutine to plot a bar graph
! Input (keyboard): FileName
! Input (file):     Number of defects per hour
! Output:           Bar graph displaying elements of array Count
!-----------------------------------------------------------------------

  IMPLICIT NONE
  INTEGER, PARAMETER :: MaxDefective = 5
  INTEGER, DIMENSION(0:MaxDefective) :: Count = 0
  INTEGER :: NumDefects, End_of_File
  CHARACTER(20) :: FileName

  ! Get file name, open the file as unit 15

  WRITE (*, '(1X, A)', ADVANCE = "NO") "Enter name of data file: "
  READ *, FileName
  OPEN (UNIT = 15, FILE = FileName, STATUS = "OLD")

  ! While there is more data, read # of defective parts and
  ! increment appropriate counter

  DO
     READ (15, *, IOSTAT = End_of_File) NumDefects
     IF (End_of_File < 0) EXIT
     ! If end of file reached, terminate repetition

     ! Otherwise continue with the following
     NumDefects = MIN(NumDefects, MaxDefective)
     Count(NumDefects) = Count(NumDefects) + 1
  END DO

  CALL DrawBarGraph(Count, MaxDefective, "Defectives", &
                    "Number of Hours")

  CLOSE (15)

CONTAINS

  !-DrawBarGraph--------------------------------------------------------
  ! Subroutine to plot a bar graph representation of a frequency
  ! distribution.  Identifiers used are:
  !   Frequency             : array of frequencies
  !   NumFrequencies        : number of frequencies
  !   MaxFrequency          : largest frequency
  !   Vertical_Axis_Label   : label for vertical axis
  !   Horizontal_Axis_Label : label for horizontal axis
  !   Number_of_Bars        : size of the array Bar (named constant)
  !   Bar                   : character array used to print one bar
  !                            of bar graph
  !   I, J                  : subscripts
  !
  ! Accepts:  Array Frequency, integer NumFrequencies, and character
  !           strings Vertical_Axis_Label and Horizontal_Axis_Label
  ! Output:   A bar graph of the elements of Frequency
  !---------------------------------------------------------------------

  SUBROUTINE DrawBarGraph(Frequency, NumFrequencies, &
             Vertical_Axis_Label, Horizontal_Axis_Label)

    INTEGER, INTENT(IN) :: NumFrequencies
    INTEGER, DIMENSION (0:NumFrequencies), INTENT(IN) :: Frequency
    CHARACTER(*) :: Vertical_Axis_Label, Horizontal_Axis_Label
    INTEGER ::  I, J, MaxFrequency
    INTEGER, PARAMETER :: Number_of_Bars = 20
    CHARACTER(3), DIMENSION(Number_of_Bars) :: Bar

    PRINT '(//1X, A)', Vertical_Axis_Label
    MaxFrequency = MAXVAL(Frequency)

    DO I = 0, MaxFrequency
       Bar = " "
       DO J = 1, Frequency(I)
          Bar(J) = "***"
       END DO
       PRINT '(1X, I10, 21A)', I, ":", Bar
    END DO

    PRINT '(11X, 80A)', (".", I = 0, 3 * MaxFrequency)
    PRINT '(9X, 20I3)', (I, I = 0, MaxFrequency)
    PRINT '(11X, A)', Horizontal_Axis_Label
  
  END SUBROUTINE DrawBarGraph
  
END PROGRAM Frequency_Distribution_2
