-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathDay19.java
175 lines (153 loc) · 5.72 KB
/
Day19.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
163
164
165
166
167
168
169
170
171
172
173
174
175
package aoc18;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
// part 1 of this challenge is self-explanatory. part 2 was very tricky.
// I actually don't know if my solution for part 2 works for every input out
// there
// To solve part 2, I simply printed the registers before and after every
// instruction and
// tried to figure out what the program is actually trying to accomplish
// it becomes apparent that the program is summing up the factors of a
// number
// that gets calculated at the beginning stage and stays constant at
// register 2. The sum of the factors of this number gets saved at register 0
// the target number is fully calculated when register 0 turns from 1 to 0.
// That's where it simply becomes a matter
// of summing up the factors and returning that sum which is what ends up in
// register 0 after the program finishes
public class Day19 {
// the register the instruction pointer is binded to
private int ipBinding;
// written opcodes of the instruction
private List<String> instructionOpcodes;
// instructions
private List<int[]> instructions;
// the main registers
private int[] registers;
public Day19(File inputFile) throws IOException {
instructions = new ArrayList<int[]>();
instructionOpcodes = new ArrayList<String>();
parseInput(inputFile);
registers = new int[] { 0, 0, 0, 0, 0, 0 };
}
// part 1
public int run() {
int count = 0;
int instructionPointer = 0;
int numOfInstructions = instructions.size();
while (instructionPointer < numOfInstructions) {
String instructionOpcode = instructionOpcodes.get(instructionPointer);
int[] instruction = instructions.get(instructionPointer);
registers[ipBinding] = instructionPointer;
if(count > 50000000)
System.out.println(Arrays.toString(registers) + " " + instructionOpcode + " " + Arrays.toString(instruction) + " " + count);
executeInstruction(instructionOpcode, instruction, registers);
if(count > 50000000){
System.out.println(Arrays.toString(registers) + " " + instructionOpcode + " " + Arrays.toString(instruction));
System.out.println();
}
instructionPointer = registers[ipBinding];
instructionPointer++;
count++;
}
return registers[0];
}
// part 2
public long run2() {
registers = new int[] { 1, 0, 0, 0, 0, 0 };
int instructionPointer = 0;
// run until the target number is fully calculated at register 2
while (registers[0] == 1) {
String instructionOpcode = instructionOpcodes.get(instructionPointer);
int[] instruction = instructions.get(instructionPointer);
registers[ipBinding] = instructionPointer;
executeInstruction(instructionOpcode, instruction, registers);
instructionPointer = registers[ipBinding];
instructionPointer++;
}
return sumOfFactors(registers[2]);
}
static void executeInstruction(String opcode, int[] instruction, int[] registers) {
if (opcode.equals("addi"))
Day16.addi(registers, instruction);
else if (opcode.equals("addr"))
Day16.addr(registers, instruction);
else if (opcode.equals("mulr"))
Day16.mulr(registers, instruction);
else if (opcode.equals("muli"))
Day16.muli(registers, instruction);
else if (opcode.equals("banr"))
Day16.banr(registers, instruction);
else if (opcode.equals("bani"))
Day16.bani(registers, instruction);
else if (opcode.equals("borr"))
Day16.borr(registers, instruction);
else if (opcode.equals("bori"))
Day16.bori(registers, instruction);
else if (opcode.equals("setr"))
Day16.setr(registers, instruction);
else if (opcode.equals("seti"))
Day16.seti(registers, instruction);
else if (opcode.equals("gtir"))
Day16.gtir(registers, instruction);
else if (opcode.equals("gtri"))
Day16.gtri(registers, instruction);
else if (opcode.equals("gtrr"))
Day16.gtrr(registers, instruction);
else if (opcode.equals("eqir"))
Day16.eqir(registers, instruction);
else if (opcode.equals("eqri"))
Day16.eqri(registers, instruction);
else if (opcode.equals("eqrr"))
Day16.eqrr(registers, instruction);
}
private void parseInput(File inputFile) throws IOException {
Scanner sc = new Scanner(inputFile);
String currentLine = "";
while (sc.hasNext()) {
currentLine = sc.nextLine();
if (currentLine.startsWith("#")) {
ipBinding = Integer.parseInt(Character.toString(currentLine.charAt(currentLine.length() - 1)));
} else {
instructionOpcodes.add(currentLine.substring(0, 4));
String[] instructionsAsString = currentLine.substring(5, currentLine.length()).split(" ");
int[] currentInstructions = new int[4];
// the real opcode has no bearing on the operation in this case
// since we already know what every instruction does, so we set
// it to -1
currentInstructions[0] = -1;
currentInstructions[1] = Integer.parseInt(instructionsAsString[0]);
currentInstructions[2] = Integer.parseInt(instructionsAsString[1]);
currentInstructions[3] = Integer.parseInt(instructionsAsString[2]);
instructions.add(currentInstructions);
}
}
sc.close();
}
// helper method for part 2
// returns the sum of the factors of the given integer
public static long sumOfFactors(int num) {
long sumOfFactors = 0;
int i = 1;
while (i <= num) {
if (num % i == 0) {
sumOfFactors += num / i;
}
i++;
}
return sumOfFactors;
}
public void setRegisterZero(int val) {
registers[0] = val;
}
public static void main(String[] args) throws IOException {
Day19 test = new Day19(new File("C:\\Users\\Timucin\\Desktop\\Advent of code 2018\\Day 19\\InputFile1.txt"));
// int result1 = test.run();
long res2 = test.run2();
System.out.println(res2);
}
}