/home/wpollock1/public_html/restricted/Java1/Histogram.java

/* A Java non-GUI program that displays a histogram.  This program
 * can be used to show how many students answered each question
 * incorrectly on an exam of 25 questions.  Note the array is
 * declared with a size of 25+1; this is so I can use indexes
 * of 1..25 instead of 0..24.  Also note the way I printed
 * either one or two leading spaces, so the output would line up.
 *
 * To create a runnable jar: jar -cfe Histogram.jar Histogram Histogram.class
 * (Note there's no trivial way to include utils.jar in Histogram.jar!)
 *
 * Written 2000 Wayne Pollock, Tampa, FL USA.
 * Modified 2006 to include Scanner and other features.
 * Modified 2020 some minor refactoring done.
 * TODO: Detect if stdin or stdout is redirected using System.console;
 *       if so, don't print a prompt else print one.
 */

import java.util.*;
import utils.*;

class Histogram {
    private static final int NUM_QUESTIONS = 25;

    public static void main ( String [] args ) {
        int[] questionFreq = collectFrequencyData();
        System.out.println( "\n\t Histogram showing how many students" );
        System.out.println( "\t answered each question wrong:\n\n" );
        System.out.print( generateHistogram( questionFreq ) );
    }

    /** Reads data points (numbers 1..24) from standard input and
     *  calulates the frequency of each one.
     * @returns the frequency data
     */
    private static int[] collectFrequencyData () {
        int[] question = new int[ NUM_QUESTIONS + 1 ];  // Use indexes 1..25
        Scanner in = new Scanner( System.in );

        System.err.println( "Enter integers <= " + NUM_QUESTIONS
            + ", one per line, hit the EOF char when done:" );
        for ( ; ; ) {
            // System.out.print( "==> " );  // Prints a prompt
            try {
                int num = in.nextInt();
                if ( num < 1 || num > NUM_QUESTIONS ) {
                    System.err.println( "### Numbers must be between 1 and "
                        + NUM_QUESTIONS + "!" );
                    continue;
                }
                ++question[num];  // Increment the "num-th" counter.
            }
            catch ( InputMismatchException ime ) {
                System.err.println( "### Please enter whole numbers only!" );
                in.nextLine();  // Throw away the rest of the (bad) input.
                continue;
            }
            catch ( Exception e ) {
                break;
            }
        }
        return question;
    }

    /** Generates a horizontal non-GUI bar chart (a histogram) from the
     *  frequency data passed in.
     * @param data counts for each data point (the array index is the data point)
     * @returns the historgram
     */
    private static String generateHistogram( int[] data ) {
        // Calculate max amount of padding needed:
        int padLength = Integer.toString( NUM_QUESTIONS ).length();
        StringBuilder histogram = new StringBuilder();
        for ( int i = 1; i < data.length; ++i ) {
            histogram.append( TextKit.pad(i, padLength) + ": "
                + TextKit.lineOfStars(data[i]) + "\n" );
        }
        return histogram.toString();
    }
}