Enum with Behaviour: Operations

Problem

Model the operations PLUS (+), MINUS (-), TIMES (*), DIVIDE (/) and POWER (^) as an enum where each constant has its own symbol and its own apply(a, b) method. Every input line is: NAME a b. Print a symbol b = result, for example 3 + 4 = 7. DIVIDE cuts toward zero and prints error when b is 0. POWER has a non-negative whole exponent b. The main loop must not have a switch on the name; it finds the constant by name and calls apply.

Constraints

  • 1 <= lines <= 10^4
  • |a| <= 100
  • 0 <= b <= 5 for POWER; |b| <= 1000 otherwise

Examples

Input

PLUS 3 4
DIVIDE 7 0

Output

3 + 4 = 7
7 / 0 = error

Solutions

Best approachTime O(n * b)Space O(n)

A Java enum is a class with a fixed set of objects, so every constant can carry data and its own method. Adding a new operation means adding one constant; the main loop does not change. JavaScript has no enum, so a frozen object is the usual replacement.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several lines.
 * Output  : One equation per line.
 * Approach: Enum with behaviour.
 * Time    : O(n * b)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: Each constant of the enum has its own symbol and its own version of apply().
        enum Operation {
            PLUS("+") {
                long apply(long a, long b) {
                    return a + b;
                }
            },
            MINUS("-") {
                long apply(long a, long b) {
                    return a - b;
                }
            },
            TIMES("*") {
                long apply(long a, long b) {
                    return a * b;
                }
            },
            DIVIDE("/") {
                long apply(long a, long b) {
                    if (b == 0) {
                        throw new ArithmeticException("division by zero");
                    }
                    return a / b;
                }
            },
            POWER("^") {
                long apply(long a, long b) {
                    long result = 1;
                    for (long i = 0; i < b; i++) {
                        result *= a;
                    }
                    return result;
                }
            };

            final String symbol;

            Operation(String symbol) {
                this.symbol = symbol;
            }

            abstract long apply(long a, long b);
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        String[] output = new String[lines.length];
        for (int i = 0; i < lines.length; i++) {
            String[] part = lines[i].split(" ");
            // Step 2: valueOf finds the constant by its name.
            Operation operation = Operation.valueOf(part[0]);
            long a = Long.parseLong(part[1]);
            long b = Long.parseLong(part[2]);
            String left = a + " " + operation.symbol + " " + b + " = ";
            // Step 3: A division by zero throws. We catch it and print "error".
            try {
                output[i] = left + operation.apply(a, b);
            } catch (ArithmeticException error) {
                output[i] = left + "error";
            }
        }
        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. How does adding a new operation affect the main loop?