/**
 * Class Input reads a line from the system console (System.in).
 * It displays a numbered prompt.
 */
import java.util.Scanner;
public class Input {
    // Static members and methods
    private static int lineNo = 0;
    static Scanner sc = new Scanner(System.in).useDelimiter("\\n");
    public static Input readInput() {
        return new Input();
    }
    // Instance members and methods
    private final String line;
    private Input() {
        lineNo++;
	System.out.printf("[%d]=> ", lineNo);
	this.line = sc.next();
    }
    public String getLine() {
	return this.line;
    }
    public int getLineNum() {
	return this.lineNo;
    }
}
/**
 * This class serves only to store the result of the calculation
 * in the form of a message string. A display method is provided
 * to print the message to console (System.out).
 */
public class Result {
    private final String message;
    
    public Result(String m) {
	this.message = m;
    }
    public void display() {
	System.out.println(message);
    }
}
/**
 * Class Statement is the workhorse of the calculator.
 * It initializes the hashtable to store the command and its associated
 * lambda function. To run the command, its name is used to lookup the table
 * to retrieve the lambda, which is then applied to the arguments.
 *
 * There is a lot of code to handle errors, which are due to:
 * (a) unknown command, (b) wrong type of arguments, (c) too many or too few
 * arguments. Such code clutters the main code and obscures the key idea.
 * There is room for improvement!
 */
import java.util.Scanner;
import java.util.function.Function;
import java.util.NoSuchElementException;
import java.util.InputMismatchException;
import java.util.Hashtable;
public class Statement {
    // static members and methods
    // This stores the function for each command
    private static Hashtable < String, Function < Double[], Double >> commandTable;
    // This stores the number of arguments for each command
    private static Hashtable < String, Integer > argsTable;
    public static Statement parse(Input input) {
        return new Statement(input.getLine());
    }
    /**
     * Error input, return 0.0
     * Accept a double array with 0 elements = 0 argument
     */
    private static final Function < Double[], Double >
        error = x - > 0.0;
    /**
     * Addition
     * Accept a double array with 2 elements = 2 arguments
     * Example: add 1 2
     */
    private static final Function < Double[], Double >
        addition = x - > x[0] + x[1];
    /**
     * Multiplication
     * Accept a double array with 2 elements = 2 arguments
     * Example: mult 3 4
     */
    private static final Function < Double[], Double >
        multiplication = x - > x[0] * x[1];
    /**
     * Reciprocal
     * Accept a double array with 1 element = 1 argument
     * Example: recip 5
     */
    private static final Function < Double[], Double >
        reciprocal = x - > 1.0 / x[0];
    /**
     * Percentage after Multiplication
     * Accept a double array with 2 elements = 2 arguments
     * Example: % 6 7
     */
    private static final Function < Double[], Double >
        percentage = x - > x[0] * x[1] / 100.0;
    // Initialization
    public static void initialize() {
        commandTable = new Hashtable < > ();
        argsTable = new Hashtable < > ();
        /**
         * Error input, return 0.0
         * Accept a double array with 0 elements = 0 argument
         */
        commandTable.put("err", error);
        argsTable.put("err", 0);
        /**
         * Addition
         * Accept a double array with 2 elements = 2 arguments
         */
        commandTable.put("add", addition);
        argsTable.put("add", 2);
        /**
         * Multiplication
         * Accept a double array with 2 elements = 2 arguments
         */
        commandTable.put("mult", multiplication);
        argsTable.put("mult", 2);
        /**
         * Reciprocal
         * Accept a double array with 1 element = 1 argument
         */
        commandTable.put("recip", reciprocal);
        argsTable.put("recip", 1);
        /**
         * Percentage after Multiplication
         * Accept a double array with 2 elements = 2 arguments
         */
        commandTable.put("%", percentage);
        argsTable.put("%", 2);
    }
    // Instance member and methods
    private String command;
    private Double[] arguments;
    private String message;
    // Input Method
    public Statement(String input) {
        /**
         * Input format: <command> <arg1> [<arg2>]
         *
         * Example:
         * add    1 2
         * mult   3 4
         * recip  5
         * %      6 7
         */
        Scanner sc = new Scanner(input);
        // Parse command
        String c = sc.next();
        // If the command is not err, add, mult, recip or %
        if (!commandTable.containsKey(c)) {
            this.command = "err";
            this.message = String.format("Bad command! %s", c);
            return;
        }
        this.command = c;
        // Parse arguments
        int numberArgs = argsTable.get(this.command);
        this.arguments = new Double[numberArgs];
        try {
            for (int i = 0; i < numberArgs; i++) {
                this.arguments[i] = sc.nextDouble();
            }
            if (sc.hasNext()) {
                this.command = "err";
                this.message = "Too many arguments!";
            }
        } catch (InputMismatchException e) {
            this.command = "err";
            this.message = "Bad arguments!";
        } catch (NoSuchElementException e) {
            this.command = "err";
            this.message = "Too few arguments!";
        }
    }
    public Result evaluate() {
        if (!this.command.equals("err")) {
            // commandTable.get(this.command): Function object
            // this.arguments: Double[] object
            double r = commandTable.get(this.command).apply(this.arguments);
            this.message = String.format("%f", r);
        }
        return new Result(this.message);
    }
}
/**
 * Calc.java implements a simple, command-line calculator.
 * User enters command in the form: <command> <arg1> <arg2>
 * Example: add 3 5
 * Currently, only 4 command are implemented: add, mult, recip, %,
 * denoting addition, multiplcation, reciprocal, and percentage, respectively.
 * To compile, put all the files in the same directory:
 * Calc.java, Input.java, Statement.java, Results.java
 * Then type:
 *    javac *.java
 *    java Calc
 */
import java.util.NoSuchElementException;
public class Calc {
    public static void main(String[] args) {
        // Initialize the calculator
        Statement.initialize();
        try {
            while (true) {
                Input input = Input.readInput();
                Statement statement = Statement.parse(input);
                Result result = statement.evaluate();
                result.display();
            }
        } catch (NoSuchElementException e) {
            // break out of while loop; end program
        }
    }
}