-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathDay18.java
162 lines (139 loc) · 3.94 KB
/
Day18.java
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package com.sbaars.adventofcode.year17.days;
import com.sbaars.adventofcode.year17.Day2017;
import java.util.HashMap;
import java.util.Map;
public class Day18 extends Day2017 {
public Day18() {
super(18);
}
public static void main(String[] args) {
new Day18().printParts();
}
@Override
public Object part1() {
String[] instructions = dayStrings();
Map<String, Long> registers = new HashMap<>();
long lastSound = 0;
int ip = 0; // instruction pointer
while (ip >= 0 && ip < instructions.length) {
String[] parts = instructions[ip].split(" ");
String cmd = parts[0];
String x = parts[1];
String y = parts.length > 2 ? parts[2] : null;
long xVal = getValue(registers, x);
long yVal = y != null ? getValue(registers, y) : 0;
switch (cmd) {
case "snd":
lastSound = xVal;
break;
case "set":
registers.put(x, yVal);
break;
case "add":
registers.put(x, xVal + yVal);
break;
case "mul":
registers.put(x, xVal * yVal);
break;
case "mod":
registers.put(x, xVal % yVal);
break;
case "rcv":
if (xVal != 0) {
return lastSound;
}
break;
case "jgz":
if (xVal > 0) {
ip += yVal - 1; // -1 because we'll add 1 at the end
}
break;
}
ip++;
}
return lastSound;
}
private static long getValue(Map<String, Long> registers, String value) {
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
return registers.getOrDefault(value, 0L);
}
}
private static class Program {
private final Map<String, Long> registers = new HashMap<>();
private final java.util.Queue<Long> messageQueue = new java.util.LinkedList<>();
private final String[] instructions;
private int ip = 0; // instruction pointer
private int sendCount = 0;
private boolean isWaiting = false;
Program(String[] instructions, int id) {
this.instructions = instructions;
registers.put("p", (long) id);
}
boolean isTerminated() {
return ip < 0 || ip >= instructions.length;
}
void addToQueue(long value) {
messageQueue.add(value);
isWaiting = false;
}
boolean execute(Program other) {
if (isTerminated()) return false;
String[] parts = instructions[ip].split(" ");
String cmd = parts[0];
String x = parts[1];
String y = parts.length > 2 ? parts[2] : null;
long xVal = getValue(registers, x);
long yVal = y != null ? getValue(registers, y) : 0;
switch (cmd) {
case "snd":
other.addToQueue(xVal);
sendCount++;
break;
case "set":
registers.put(x, yVal);
break;
case "add":
registers.put(x, xVal + yVal);
break;
case "mul":
registers.put(x, xVal * yVal);
break;
case "mod":
registers.put(x, xVal % yVal);
break;
case "rcv":
if (messageQueue.isEmpty()) {
isWaiting = true;
return false;
}
registers.put(x, messageQueue.poll());
break;
case "jgz":
if (xVal > 0) {
ip += yVal - 1; // -1 because we'll add 1 at the end
}
break;
}
ip++;
return true;
}
}
@Override
public Object part2() {
String[] instructions = dayStrings();
Program prog0 = new Program(instructions, 0);
Program prog1 = new Program(instructions, 1);
while (true) {
boolean prog0Moved = prog0.execute(prog1);
boolean prog1Moved = prog1.execute(prog0);
// Check for deadlock or termination
if ((!prog0Moved && !prog1Moved) ||
(prog0.isTerminated() && prog1.isTerminated())) {
break;
}
}
return prog1.sendCount;
}
}