Shape Area (Sealed Types and Pattern Matching)
Problem
Read one line: a shape name and its numbers. The shapes are: rect width height, square side, triangle base height. Print the area with one decimal (for example 12.0 or 4.5). For any other shape name print Unknown shape. All numbers are positive integers.
Constraints
- 1 <= numbers <= 10^6
Examples
Input
triangle 3 3
Output
4.5
Solutions
With an interface and one class per shape, the code is long. The if-else chain that picks the class is easy to break when a new shape is added.
/*
* Problem : Process one line of text.
* Input : One line of text.
* Output : The area with one decimal.
* Approach: One class per shape.
* Time : O(1)
* Space : O(1)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: An interface for all shapes, and one class for each shape. The area is stored as "twice the area",
// so the triangle formula base * height / 2 stays an exact integer.
interface Shape {
long twiceArea();
}
static class Rect implements Shape {
final long width;
final long height;
Rect(long width, long height) {
this.width = width;
this.height = height;
}
public long twiceArea() {
return 2 * width * height;
}
}
static class Square implements Shape {
final long side;
Square(long side) {
this.side = side;
}
public long twiceArea() {
return 2 * side * side;
}
}
static class Triangle implements Shape {
final long base;
final long height;
Triangle(long base, long height) {
this.base = base;
this.height = height;
}
public long twiceArea() {
return base * height;
}
}
// This method solves the task. It receives the input and returns the answer.
static String solve(String s) {
// Step 2: Read the shape name and the numbers.
String[] t = s.trim().split("\\s+");
Shape shape;
// Step 3: Create the object that fits the name.
if (t[0].equals("rect")) {
shape = new Rect(Long.parseLong(t[1]), Long.parseLong(t[2]));
} else if (t[0].equals("square")) {
shape = new Square(Long.parseLong(t[1]));
} else if (t[0].equals("triangle")) {
shape = new Triangle(Long.parseLong(t[1]), Long.parseLong(t[2]));
} else {
return "Unknown shape";
}
// Step 4: Print the area with one decimal. twiceArea / 2 is the whole part, and the remainder gives .5 or .0.
long twice = shape.twiceArea();
return (twice / 2) + "." + (twice % 2 == 1 ? "5" : "0");
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.hasNextLine() ? scanner.nextLine() : "";
System.out.println(solve(s));
}
}
Hints (1)
- Why do we store twice the area?