Exception Unwinding Trace
Problem
Level 1 calls level 2, level 2 calls level 3, and so on up to level d. Every level prints enter i, then calls the next level, and has a finally block that prints finally i. At level t (if t > 0) an exception is thrown right after enter t, with the text throw at t printed just before. The level c (if c > 0) has a catch block that prints caught at c and stops the exception; with c = 0 no level catches it and the main program prints uncaught after the unwinding. If t = 0 nothing is thrown. Print all the lines in the order they happen. Input: d, t and c (0 <= c <= t <= d).
Constraints
- 1 <= d <= 8
- 0 <= c <= t <= d
Examples
Input
3 3 1
Output
enter 1 enter 2 enter 3 throw at 3 finally 3 finally 2 caught at 1 finally 1
Solutions
An exception leaves a method at once, but finally blocks of every level on the way still run, from the deepest to the highest. The catch at level c ends the travel; after it the levels above continue normally.
/*
* Problem : Trace the unwinding.
* Input : d, t and c.
* Output : The trace lines.
* Approach: Real exceptions.
* Time : O(d)
* Space : O(d)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: Each level enters, calls the next level, and always runs its finally block.
private static void run(int level, int d, int t, int c, java.util.List<String> out) {
out.add("enter " + level);
try {
if (level == t) {
out.add("throw at " + level);
throw new IllegalStateException("boom");
}
if (level < d) {
run(level + 1, d, t, c, out);
}
} catch (IllegalStateException e) {
// Step 2: Only level c handles the exception. Other levels throw it again to their caller.
if (level == c) {
out.add("caught at " + level);
} else {
throw e;
}
} finally {
out.add("finally " + level);
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(long a, long b, long m) {
java.util.List<String> out = new java.util.ArrayList<String>();
// Step 3: The main program catches what nobody caught.
try {
run(1, (int) a, (int) b, (int) m, out);
} catch (IllegalStateException e) {
out.add("uncaught");
}
return out.toArray(new String[0]);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long a = scanner.nextLong();
long b = scanner.nextLong();
long m = scanner.nextLong();
System.out.println(String.join("\n", solve(a, b, m)));
}
}
Hints (2)
- In which order do the finally blocks run?
- What happens after the catch at level c?