2024st
This commit is contained in:
153
src/j2024/ST/AriadneIterator.java
Normal file
153
src/j2024/ST/AriadneIterator.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package j2024.ST;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
public class AriadneIterator implements Iterator<Node> {
|
||||
|
||||
private final Node entry;
|
||||
private Stack<Node> ariadnesThread;
|
||||
private Set<Node> visited;
|
||||
private State currentState;
|
||||
|
||||
public AriadneIterator(Node entry) {
|
||||
this.entry = entry;
|
||||
this.ariadnesThread = new Stack<>();
|
||||
this.visited = new HashSet<>();
|
||||
this.currentState = new Starting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentState.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
step();
|
||||
|
||||
if (ariadnesThread.empty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return ariadnesThread.peek();
|
||||
}
|
||||
|
||||
private void step() {
|
||||
currentState.step();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
ariadnesThread.push(entry);
|
||||
visited.add(entry);
|
||||
}
|
||||
|
||||
private boolean foundMiraculix() {
|
||||
return ariadnesThread.peek().hasMiraculix();
|
||||
}
|
||||
|
||||
private Node nextForward() {
|
||||
Node current = ariadnesThread.peek();
|
||||
|
||||
for (Node next : current.getReachable()) {
|
||||
if (!visited.contains(next)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void seekingStep() {
|
||||
Node next = nextForward();
|
||||
|
||||
if (next != null) {
|
||||
ariadnesThread.push(next);
|
||||
visited.add(next);
|
||||
} else {
|
||||
retreatingStep();
|
||||
}
|
||||
}
|
||||
|
||||
private void retreatingStep() {
|
||||
ariadnesThread.pop();
|
||||
}
|
||||
|
||||
private interface State {
|
||||
void step();
|
||||
|
||||
boolean hasNext();
|
||||
}
|
||||
|
||||
private class Starting implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
init();
|
||||
|
||||
if (foundMiraculix()) {
|
||||
currentState = new MissionAccomplished();
|
||||
} else {
|
||||
currentState = new SeekingMiraculix();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class SeekingMiraculix implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
seekingStep();
|
||||
|
||||
if (!ariadnesThread.empty() && foundMiraculix()) {
|
||||
currentState = new MissionAccomplished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MissionAccomplished implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
retreatingStep();
|
||||
|
||||
if (ariadnesThread.size() == 1 && ariadnesThread.peek() == entry) {
|
||||
currentState = new Finished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return ariadnesThread.size() > 1;
|
||||
}
|
||||
}
|
||||
|
||||
private class Finished implements State {
|
||||
|
||||
@Override
|
||||
public void step() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/j2024/ST/AriadneIteratorTest.java
Normal file
24
src/j2024/ST/AriadneIteratorTest.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package j2024.ST;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AriadneIteratorTest {
|
||||
|
||||
@Test
|
||||
public void testSmallVillage() {
|
||||
Node entry = SampleVillage.createSmallVillage();
|
||||
|
||||
AriadneIterator iter = new AriadneIterator(entry);
|
||||
|
||||
assertEquals(1, iter.next().getNumber());
|
||||
assertEquals(2, iter.next().getNumber());
|
||||
assertEquals(3, iter.next().getNumber());
|
||||
assertEquals(2, iter.next().getNumber());
|
||||
assertEquals(1, iter.next().getNumber());
|
||||
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
}
|
||||
38
src/j2024/ST/Node.java
Normal file
38
src/j2024/ST/Node.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package j2024.ST;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Node {
|
||||
|
||||
private final int number;
|
||||
private boolean miraculix;
|
||||
private Set<Node> reachable;
|
||||
|
||||
public Node(int number) {
|
||||
this.number = number;
|
||||
this.miraculix = false;
|
||||
this.reachable = new HashSet<>();
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public boolean hasMiraculix() {
|
||||
return miraculix;
|
||||
}
|
||||
|
||||
public void setMiraculix(boolean miraculix) {
|
||||
this.miraculix = miraculix;
|
||||
}
|
||||
|
||||
public Set<Node> getReachable() {
|
||||
return reachable;
|
||||
}
|
||||
|
||||
public void addReachable(Node node) {
|
||||
reachable.add(node);
|
||||
node.reachable.add(this);
|
||||
}
|
||||
}
|
||||
19
src/j2024/ST/SampleVillage.java
Normal file
19
src/j2024/ST/SampleVillage.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package j2024.ST;
|
||||
|
||||
public class SampleVillage {
|
||||
|
||||
public static Node createSmallVillage() {
|
||||
Node n1 = new Node(1);
|
||||
Node n2 = new Node(2);
|
||||
Node n3 = new Node(3);
|
||||
Node n4 = new Node(4);
|
||||
|
||||
n3.setMiraculix(true);
|
||||
|
||||
n1.addReachable(n2);
|
||||
n2.addReachable(n3);
|
||||
n3.addReachable(n4);
|
||||
|
||||
return n1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user