Interval Class: Overlap and Union

Problem

An interval has a low and a high end (low <= high, both ends included). Commands: make NAME LOW HIGH, length NAME (HIGH - LOW), overlaps A B (true or false; intervals that only touch at one point do overlap), union A B (print LOW HIGH of the smallest interval that covers both, if they overlap; otherwise print none).

Constraints

  • 1 <= commands <= 100
  • LOW <= HIGH

Examples

Input

make a 1 5
make b 4 9
union a b

Output

1 9

Solutions

Best approachTime O(n)Space O(n)

The Interval class hides the two ends and gives three clear methods. The overlap test (each one starts before the other ends) is in one place and is reused by union.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Run the commands.
 * Input   : Command lines.
 * Output  : One line per answer.
 * Approach: Interval class
 * Time    : O(n)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: An Interval keeps its two ends and hides them. The overlap rule is written once, here.
        static class Interval {
            private final long low;
            private final long high;

            Interval(long low, long high) {
                this.low = low;
                this.high = high;
            }

            long length() {
                return high - low;
            }

            // Step 2: Two closed intervals overlap when each starts before the other one ends.
            boolean overlaps(Interval other) {
                return low <= other.high && other.low <= high;
            }

            // Step 3: The union of two overlapping intervals runs from the smaller low to the larger high.
            Interval union(Interval other) {
                return new Interval(Math.min(low, other.low), Math.max(high, other.high));
            }

            String text() {
                return low + " " + high;
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        java.util.Map<String, Interval> named = new java.util.HashMap<String, Interval>();
        java.util.List<String> out = new java.util.ArrayList<String>();
        for (String line : lines) {
            String[] part = line.split(" ");
            if (part[0].equals("make")) {
                named.put(part[1], new Interval(Long.parseLong(part[2]), Long.parseLong(part[3])));
            } else if (part[0].equals("length")) {
                out.add(String.valueOf(named.get(part[1]).length()));
            } else {
                Interval first = named.get(part[1]);
                Interval second = named.get(part[2]);
                if (part[0].equals("overlaps")) {
                    out.add(String.valueOf(first.overlaps(second)));
                } else {
                    out.add(first.overlaps(second) ? first.union(second).text() : "none");
                }
            }
        }
        return out.toArray(new String[0]);
    }

    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 (2)
  1. Why do intervals that touch at one point overlap here?
  2. What is the union of two intervals that do not overlap?