Memento: Editor Snapshots
Problem
Build a text editor with snapshots. Commands: TYPE text (add the text to the end of the document; the text is everything after the first space and may contain spaces), SNAPSHOT (save the current text; print its number: 1 for the first snapshot, 2 for the second, ...), RESTORE n (replace the document by snapshot n; print unknown for a number that does not exist) and SHOW (print the document, or (empty) if it has no text). TYPE and a good RESTORE print ok. Use the memento pattern: the editor creates and reads snapshot objects, and another object (the caretaker) only stores them.
Constraints
- 1 <= lines <= 1000
Examples
Input
TYPE hi SNAPSHOT TYPE ! SHOW RESTORE 1 SHOW
Output
ok 1 ok hi! ok hi
Solutions
The editor owns its state and decides what a snapshot contains. The caretaker keeps the snapshots but cannot read them, so the editor's internals stay hidden. Undo history, save points and game checkpoints work this way.
/*
* Problem : Process lines.
* Input : Several command lines.
* Output : One result per command.
* Approach: Editor, memento and caretaker.
* Time : O(n * text length)
* Space : O(snapshots * text length)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: A Memento is a sealed snapshot. Only the editor looks inside it.
static class Memento {
private final String text;
Memento(String text) {
this.text = text;
}
}
// Step 2: The editor creates snapshots and restores from them.
static class Editor {
private String text = "";
void type(String more) {
text += more;
}
Memento save() {
return new Memento(text);
}
void restore(Memento memento) {
text = memento.text;
}
String show() {
return text.isEmpty() ? "(empty)" : text;
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
Editor editor = new Editor();
// Step 3: The caretaker is only a list of mementos. It cannot read or change them.
java.util.List<Memento> caretaker = new java.util.ArrayList<Memento>();
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
if (line.startsWith("TYPE ")) {
editor.type(line.substring(5));
output[i] = "ok";
} else if (line.equals("SNAPSHOT")) {
caretaker.add(editor.save());
output[i] = String.valueOf(caretaker.size());
} else if (line.startsWith("RESTORE ")) {
int number = Integer.parseInt(line.substring(8).trim());
if (number >= 1 && number <= caretaker.size()) {
editor.restore(caretaker.get(number - 1));
output[i] = "ok";
} else {
output[i] = "unknown";
}
} else {
output[i] = editor.show();
}
}
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()) {
all.add(scanner.nextLine());
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (2)
- Who may look inside a memento?
- What does the caretaker store?