Skip to content

Commit a2c7755

Browse files
committed
Day 17 part 1
1 parent 6fc62f0 commit a2c7755

File tree

4 files changed

+217
-1
lines changed

4 files changed

+217
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ Just a small side note: I'm getting more and more fond of backing grid-like puzz
152152

153153
## Day 17: Chronospatial Computer
154154

155-
155+
I love an emulator day! I had fun doing part 1. Now seeing part 2...I'm less enthused about an emulator day. I'll try brute force first and see how it goes.
156156

157157
## Day 18: RAM Run
158158

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package com.robabrazado.aoc2024.day17;
2+
3+
import java.math.BigInteger;
4+
import java.util.ArrayList;
5+
import java.util.Iterator;
6+
import java.util.List;
7+
import java.util.regex.Matcher;
8+
import java.util.regex.Pattern;
9+
import java.util.stream.Stream;
10+
11+
public class Computer {
12+
private static final BigInteger MAX_VALUE = BigInteger.valueOf(Integer.MAX_VALUE);
13+
private static final BigInteger BIG8 = BigInteger.valueOf(8);
14+
private static final Pattern REGISTER_PATTERN = Pattern.compile("^Register ([ABC]): (\\d+)$");
15+
private static final String PROGRAM_INPUT_START = "Program: ";
16+
17+
private BigInteger registerA = null;
18+
private BigInteger registerB = null;
19+
private BigInteger registerC = null;
20+
21+
public Computer() {
22+
23+
}
24+
25+
public void initialize(BigInteger a, BigInteger b, BigInteger c) {
26+
if (a == null || b == null || c == null) {
27+
throw new IllegalArgumentException("Computer cannot be initialized with null values");
28+
}
29+
this.registerA = a;
30+
this.registerB = b;
31+
this.registerC = c;
32+
return;
33+
}
34+
35+
BigInteger a() {
36+
return this.registerA;
37+
}
38+
39+
BigInteger b() {
40+
return this.registerB;
41+
}
42+
43+
BigInteger c() {
44+
return this.registerC;
45+
}
46+
47+
public List<Integer> executeProgram(List<Integer> program) {
48+
List<Integer> output = new ArrayList<Integer>();
49+
Operator[] operators = Operator.values();
50+
int pointer = 0;
51+
int programLen = program != null ? program.size() : 0;
52+
53+
while (pointer < programLen) {
54+
Operator operator = operators[program.get(pointer++)];
55+
Integer input = program.get(pointer++);
56+
57+
switch (operator) {
58+
case ADV:
59+
this.registerA = this.registerA.divide(BigInteger.TWO.pow(this.getSafeCombo(input)));
60+
break;
61+
case BXL:
62+
this.registerB = this.registerB.xor(Operand.getLiteralOperand(input));
63+
break;
64+
case BST:
65+
this.registerB = Operand.getComboOperand(input, this).remainder(BIG8);
66+
break;
67+
case JNZ:
68+
if (!this.registerA.equals(BigInteger.ZERO)) {
69+
pointer = Operand.getLiteralOperand(input).intValue();
70+
}
71+
break;
72+
case BXC:
73+
this.registerB = this.registerB.xor(this.registerC);
74+
break;
75+
case OUT:
76+
output.add(Operand.getComboOperand(input, this).remainder(BIG8).intValue());
77+
break;
78+
case BDV:
79+
this.registerB = this.registerA.divide(BigInteger.TWO.pow(this.getSafeCombo(input)));
80+
break;
81+
case CDV:
82+
this.registerC = this.registerA.divide(BigInteger.TWO.pow(this.getSafeCombo(input)));
83+
break;
84+
default:
85+
throw new RuntimeException("Unsupported operator: " + operator.name());
86+
}
87+
}
88+
89+
return output;
90+
}
91+
92+
private int getSafeCombo(int input) {
93+
BigInteger result = Operand.getComboOperand(input, this);
94+
if (result.compareTo(MAX_VALUE) > 0) {
95+
// Probably (hopefully?!) this never comes up, but just to be safe...
96+
throw new RuntimeException("Unsupported exponent larger than " + MAX_VALUE.toString());
97+
}
98+
return result.intValue();
99+
}
100+
101+
// Initializes computer and runs program as specified by puzzle input
102+
// Returns comma-delimited String of program output
103+
public static String part1(Stream<String> puzzleInput) {
104+
StringBuilder result = new StringBuilder();
105+
Computer computer = new Computer();
106+
Iterator<String> it = puzzleInput.iterator();
107+
108+
computer.registerA = Computer.parseRegister(it.next(), "A");
109+
computer.registerB = Computer.parseRegister(it.next(), "B");
110+
computer.registerC = Computer.parseRegister(it.next(), "C");
111+
112+
if (!it.next().isEmpty()) {
113+
throw new RuntimeException("Malformed puzzle input; expected blank line");
114+
}
115+
116+
String programLine = it.next();
117+
if (programLine.startsWith(PROGRAM_INPUT_START)) {
118+
List<Integer> program = new ArrayList<Integer>();
119+
String[] programStrings = programLine.substring(PROGRAM_INPUT_START.length()).split(",");
120+
for (String s : programStrings) {
121+
program.add(Integer.parseInt(s));
122+
}
123+
List<Integer> output = computer.executeProgram(program);
124+
for (int o : output) {
125+
result.append(String.valueOf(o)).append(',');
126+
}
127+
result.deleteCharAt(result.length() - 1);
128+
} else {
129+
throw new RuntimeException("Malformed program input: " + programLine);
130+
}
131+
132+
return result.toString();
133+
}
134+
135+
private static BigInteger parseRegister(String line, String registerCode) {
136+
BigInteger result = null;
137+
Matcher m = REGISTER_PATTERN.matcher(line);
138+
if (m.find() && m.group(1).equals(registerCode)) {
139+
result = new BigInteger(m.group(2));
140+
}
141+
142+
if (result != null) {
143+
return result;
144+
} else {
145+
throw new RuntimeException("Malformed register input for register " + registerCode + ": " + line);
146+
}
147+
}
148+
149+
public enum Operator {
150+
ADV (),
151+
BXL (),
152+
BST (),
153+
JNZ (),
154+
BXC (),
155+
OUT (),
156+
BDV (),
157+
CDV ();
158+
}
159+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.robabrazado.aoc2024.day17;
2+
3+
import java.util.stream.Stream;
4+
5+
import com.robabrazado.aoc2024.Solver;
6+
7+
// --- Day 17: Chronospatial Computer ---
8+
public class Day17Solver extends Solver {
9+
10+
public Day17Solver() {
11+
super(17);
12+
return;
13+
}
14+
15+
@Override
16+
public String solve(Stream<String> puzzleInput, boolean partOne, boolean isTest) {
17+
return Computer.part1(puzzleInput);
18+
}
19+
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.robabrazado.aoc2024.day17;
2+
3+
import java.math.BigInteger;
4+
5+
public class Operand extends BigInteger {
6+
private static final long serialVersionUID = 1L;
7+
8+
private Operand(BigInteger v) {
9+
super(v.toByteArray());
10+
}
11+
12+
// Will always be 0-7
13+
public static Operand getLiteralOperand(Integer value) {
14+
if (value == null) {
15+
throw new IllegalArgumentException("Operand cannot have null value");
16+
}
17+
return new Operand(BigInteger.valueOf(value));
18+
}
19+
20+
// Could be anything, including possible int overflow?!
21+
public static Operand getComboOperand(Integer value, Computer computer) {
22+
if (value == null) {
23+
throw new IllegalArgumentException("Operand cannot have null value");
24+
}
25+
if (value >= 0 && value <= 3) {
26+
return Operand.getLiteralOperand(value);
27+
} else if (value == 4) {
28+
return new Operand(computer.a());
29+
} else if (value == 5) {
30+
return new Operand(computer.b());
31+
} else if (value == 6) {
32+
return new Operand(computer.c());
33+
} else {
34+
throw new IllegalArgumentException("Unrecognize opcode: " + String.valueOf(value));
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)