import java.util.Scanner;
import java.io.*;

public class Histogram
{
    public static void main(String[] args)throws FileNotFoundException{
        
        // assume scores are in a file named scores.txt in the local directory
        int numScores = getNumScores();
        int[] scores = readScores(numScores);
        int min = min(scores);
        int max = max(scores);
        drawHistogram(scores, min, max);
        
        System.out.println("\n\nDrawing the same histogram via mapping.");
        drawHistogramViaMapping(scores, min, max);

    }
    
    // Assume all elements of scores are between min and max
    public static void drawHistogram(int[] scoreData, int min, int max){
        //loop through all possible scores
        for(int score = min; score <= max; score++){
            System.out.print(score + ": ");
            // alternatively could use printf to specify the number of spaces
            // System.out.printf("%5s", score + ": ");
            
            // find the elements of scoreData that are equal to score
            // and print out a star for each one that is
            for(int index = 0; index < scoreData.length; index++){
                if( scoreData[index] == score )
                    System.out.print("*");
            }
            System.out.println();
        }
   }   
   
    // Assume all elements of scores are between min and max
    // count scores using mapping
    // This code is more complicated than the other version
    // but it only looks at each element of scoreData once
    // and not scoreData.length times
    public static void drawHistogramViaMapping(int[] scoreData, int min, int max){
        int[] tally = new int[max - min + 1];
        // read through scores once and tally each
        int index;
        for(int i = 0; i < scoreData.length; i++){
            index = scoreData[i] - min;
            tally[ index ]++;
        }
        
        // now go though the mapping of tallies and print out
        // the correct number of *s
        int score;
        for(index = 0; index < tally.length; index++){
            score = index + min;
            System.out.print( score + ": " );
            //print out the right number of *s
            for(int i = 0; i < tally[index]; i++){
                System.out.print("*");
            }
            System.out.println();
        }
   }  
    
    // Assumes scores in a file named scores.txt in the local directory
    // all tokens in scores are ints.
    public static int getNumScores() throws FileNotFoundException{
        Scanner fileScanner = new Scanner( new File("scores.txt") );
        int count = 0;
        while( fileScanner.hasNextInt() ){
            count++;
            fileScanner.nextInt();
        }
        fileScanner.close();
        return count;
    }
    
    // Assumes scores in a file named scores.txt in the local directory
    // Assumes numScores > 0   
    public static int[] readScores(int numScores) throws FileNotFoundException{
        int[] result = new int[ numScores ];
        Scanner fileScanner = new Scanner( new File("scores.txt") );
        for(int i = 0; i < numScores; i++){
            result[i] = fileScanner.nextInt();
        }
        fileScanner.close();
        return result;
    }
     
        
    // find min value in an array
    // data has at least 1 element
    public static int min(int[] data){
        int minSoFar = data[0]; // not 0
        for(int i = 1; i < data.length; i++){
            if( data[i] < minSoFar ){
                minSoFar = data[i];
            }
        }
        return minSoFar;
    }
    
    // find min value in an array
    // data has at least 1 element
    public static int max(int[] data){
        int maxSoFar = data[0]; // not 0
        for(int i = 1; i < data.length; i++){
            if( data[i] > maxSoFar ){
                maxSoFar = data[i];
            }
        }
        return maxSoFar;
    }
  
    // testing code developed when writing this program
    public static void test(){
       
        int[] sample = {-1, -10, 2 * 20, 10, -100, 100, 100, -100};
        System.out.println( min(sample) + " expected: -100" );
        System.out.println( max(sample) + " expected: 100" );
    }
}
