Student Grade Book

Problem

Build a small grade book. Commands: add <name> <score> stores one score for a student and prints ok. average <name> prints the whole-number average of that student (rounded down), or unknown if the student has no scores. best prints the name of the student with the highest average; on a tie the name that comes first alphabetically wins; print none when the book is empty.

Constraints

  • 1 <= commands <= 10^4
  • 0 <= score <= 100

Examples

Input

add amit 80
add amit 91
average amit

Output

ok
ok
85

Solutions

Best approachTime O(n log n)Space O(n)

Keeping the data in a small class (GradeBook) separates the rules from the command reading. Sorting the names first makes the tie rule easy: only a strictly better average replaces the current best.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several lines.
 * Output  : One result per command.
 * Approach: A small class holds the data.
 * Time    : O(n log n)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: The grade book keeps all scores of each student. A TreeMap keeps names in alphabetical order.
        static class GradeBook {
            private final java.util.TreeMap<String, java.util.List<Integer>> scores = new java.util.TreeMap<>();

            void add(String name, int score) {
                scores.computeIfAbsent(name, key -> new java.util.ArrayList<>()).add(score);
            }

            // Step 2: Whole-number average. The sum of non-negative scores divided by the count rounds down.
            private int averageOf(String name) {
                int sum = 0;
                for (int score : scores.get(name)) {
                    sum += score;
                }
                return sum / scores.get(name).size();
            }

            String average(String name) {
                return scores.containsKey(name) ? String.valueOf(averageOf(name)) : "unknown";
            }

            // Step 3: Walk the names in alphabetical order. Only a strictly higher average replaces the best one.
            String best() {
                String winner = "none";
                int top = -1;
                for (String name : scores.keySet()) {
                    if (averageOf(name) > top) {
                        top = averageOf(name);
                        winner = name;
                    }
                }
                return winner;
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        GradeBook book = new GradeBook();
        String[] output = new String[lines.length];
        for (int i = 0; i < lines.length; i++) {
            String[] part = lines[i].split(" ");
            // Step 4: One command gives one output line.
            if (part[0].equals("add")) {
                book.add(part[1], Integer.parseInt(part[2]));
                output[i] = "ok";
            } else if (part[0].equals("average")) {
                output[i] = book.average(part[1]);
            } else {
                output[i] = book.best();
            }
        }
        return output;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(String.join("\n", solve(lines)));
    }
}
Hints (1)
  1. Why is a TreeMap handy here?