Resources Are Closed in Reverse Order
Problem
A program opens n resources one after another (resource 1 first), then runs a body, and every resource must be closed at the end, in the reverse order of opening, also when the body fails. Print: open i for each resource, then body. If the flag f is 1, the body fails: print body failed and then (after all resources are closed) caught body failed. Between them print close i from n down to 1. Input: n and f.
Constraints
- 1 <= n <= 8
- f is 0 or 1
Examples
Input
2 1
Output
open 1 open 2 body body failed close 2 close 1 caught body failed
Solutions
The language closes every resource that was opened, in reverse order, even if the body throws. You do not write the close calls yourself, so none can be forgotten.
try-with-resources was added in Java 7. JavaScript and TypeScript use try/finally; Python uses a with block.
/*
* Problem : Trace the resources.
* Input : n and f.
* Output : The trace.
* Approach: Real try-with-resources
* Time : O(n)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: A resource prints "open" when it is created and "close" when try-with-resources closes it.
static class Resource implements AutoCloseable {
private final int id;
private final java.util.List<String> log;
Resource(int id, java.util.List<String> log) {
this.id = id;
this.log = log;
log.add("open " + id);
}
@Override
public void close() {
log.add("close " + id);
}
}
// Step 2: Each level opens one resource and runs the next level inside its try block. Java closes the resource on the way out.
static void run(int id, int n, boolean fail, java.util.List<String> log) {
if (id > n) {
log.add("body");
if (fail) {
log.add("body failed");
throw new IllegalStateException("body failed");
}
return;
}
try (Resource resource = new Resource(id, log)) {
run(id + 1, n, fail, log);
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(long a, long b) {
java.util.List<String> log = new java.util.ArrayList<String>();
// Step 3: The failure travels up through every try block. Each resource is closed before the main method catches it.
try {
run(1, (int) a, b == 1, log);
} catch (IllegalStateException e) {
log.add("caught " + e.getMessage());
}
return log.toArray(new String[0]);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long a = scanner.nextLong();
long b = scanner.nextLong();
System.out.println(String.join("\n", solve(a, b)));
}
}
Hints (2)
- Why is the close order reversed?
- When is the exception caught?