-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCrypticaSolver.java
More file actions
114 lines (97 loc) · 3.5 KB
/
CrypticaSolver.java
File metadata and controls
114 lines (97 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import java.util.*;
public class CrypticaSolver {
private static enum Direction { LEFT, UP, RIGHT, DOWN };
private static class Node {
public int depth;
public Node parent;
public Direction dir;
public Cryptica state;
public Node(Cryptica state) {
this.state = state;
}
public Node(Cryptica state, Node parent, Direction dir) {
this.state = state;
this.parent = parent;
this.dir = dir;
this.depth = parent.depth + 1;
}
public Node[] children() {
return new Node[] {
new Node(new Cryptica(state).moveRight(), this, Direction.RIGHT),
new Node(new Cryptica(state).moveLeft(), this, Direction.LEFT),
new Node(new Cryptica(state).moveUp(), this, Direction.UP),
new Node(new Cryptica(state).moveDown(), this, Direction.DOWN)
};
}
}
public static Cryptica parseBoard(String s) {
Cryptica crypt = new Cryptica(5, 7);
int[] srcR = new int[26];
int[] srcC = new int[26];
int[] dstR = new int[26];
int[] dstC = new int[26];
int templeStones = 0;
Scanner scan = new Scanner(s);
for (int r = 0; scan.hasNextLine(); r++) {
String line = scan.nextLine();
for (int c = 0; c < line.length(); c++) {
char ch = line.charAt(c);
if (ch == '@')
crypt.addMovingStone(r, c);
else if (ch == '#')
crypt.addBlockingStone(r, c);
else if (ch != '.') {
if (Character.isLowerCase(ch)) {
dstR[ch - 'a'] = r;
dstC[ch - 'a'] = c;
} else {
srcR[ch - 'A'] = r;
srcC[ch - 'A'] = c;
templeStones++;
}
}
}
}
for (int i = 0; i < templeStones; i++)
crypt.addTempleStone(srcR[i], srcC[i], dstR[i], dstC[i]);
return crypt;
}
public static Node solve(Cryptica crypt) {
HashSet<Integer> seen = new HashSet<Integer>();
Queue<Node> q = new LinkedList<Node>();
seen.add(crypt.hashCode());
q.add(new Node(crypt));
while (q.size() > 0) {
Node node = q.poll();
for (Node child : node.children()) {
int hash = child.state.hashCode();
if (!seen.contains(hash)) {
if (child.state.solved())
return child;
q.add(child);
seen.add(hash);
}
}
}
return null;
}
public static void printSolution(Node node) {
ArrayList<Direction> dirList = new ArrayList<Direction>();
while (node.parent != null) {
dirList.add(node.dir);
node = node.parent;
}
for (int i = dirList.size() - 1; i >= 0; i--)
System.out.println(dirList.get(i));
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
StringBuilder board = new StringBuilder();
while (scan.hasNextLine()) {
board.append(scan.nextLine());
board.append('\n');
}
Cryptica crypt = parseBoard(board.toString());
printSolution(solve(crypt));
}
}