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
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.
/*
* 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)
- How does adding a new operation affect the main loop?