summaryrefslogtreecommitdiff
path: root/2018/aoc2018-d21.py
diff options
context:
space:
mode:
Diffstat (limited to '2018/aoc2018-d21.py')
-rw-r--r--2018/aoc2018-d21.py253
1 files changed, 253 insertions, 0 deletions
diff --git a/2018/aoc2018-d21.py b/2018/aoc2018-d21.py
new file mode 100644
index 0000000..890b13d
--- /dev/null
+++ b/2018/aoc2018-d21.py
@@ -0,0 +1,253 @@
+#advent of code 2018
+#day 21
+#part 1 and part 2
+
+#this puzzle in my opinion was poorly worded, or I'm just overthinking
+#part 1 was suprisingly simple since it only required running the solution for day 19
+#unfortunately, bruteforcing the answer for part 2 didn't go as well
+#reading through input its possible to identify instruction jumps and determine what causes them
+#I was stuck for like 2 days for part 2: I couldn't find a bug in my reverse-engineering
+#I even run someone else's solution (modified for my input) to verify it
+#only to get another wrong answer
+#I found a second solution and I compared it to mine
+#only to find out that the issue wasn't in logic, I simply entered wrong value in 1 line
+#at least this reverse-engineering puzzle was for me more enjoyable than the 2021 one
+
+#part 1 bruteforce
+#program halts if the value at register 0 matches the value at register X
+#(register X is between 1 and 5, depends on the input)
+#in one particular instruction near the end
+#instruction 28 in my case
+#calculating this value provides part 1 result
+
+#part 2 reverse engineering
+#you can simplify the input program by reverse-engineering
+#basically the first few lines are trash, then the program is initiated with starting values
+#if condition 1 is met, program enters a loop until condition 1 is no longer true
+#after this loop, program checks if the value at register 0 is equal to corresponding register X
+#if true, program halts
+#you can print out all values at register X, first printed message is part1, last one is part 2
+
+
+###opcode functions
+#bit modified version of day 19
+def addr(before, op):
+ bef = before.copy();
+ C = bef[op[1]] + bef[op[2]];
+ bef[op[3]] = C;
+ return bef;
+def addi(before, op):
+ bef = before.copy();
+ C = bef[op[1]] + op[2];
+ bef[op[3]] = C;
+ return bef;
+
+def mulr(before, op):
+ bef = before.copy();
+ C = bef[op[1]] * bef[op[2]];
+ bef[op[3]] = C;
+ return bef;
+def muli(before, op):
+ bef = before.copy();
+ C = bef[op[1]] * op[2];
+ bef[op[3]] = C;
+ return bef;
+
+def banr(before, op):
+ bef = before.copy();
+ C = int(bef[op[1]] & bef[op[2]]);
+ bef[op[3]] = C;
+ return bef;
+def bani(before, op):
+ bef = before.copy();
+ C = int(bef[op[1]] & op[2]);
+ bef[op[3]] = C;
+ return bef;
+
+def borr(before, op):
+ bef = before.copy();
+ C = int(bef[op[1]] | bef[op[2]]);
+ bef[op[3]] = C;
+ return bef;
+def bori(before, op):
+ bef = before.copy();
+ C = int(bef[op[1]] | op[2]);
+ bef[op[3]] = C;
+ return bef;
+
+def setr(before, op):
+ bef = before.copy();
+ C = bef[op[1]];
+ bef[op[3]] = C;
+ return bef;
+def seti(before, op):
+ bef = before.copy();
+ C = op[1];
+ bef[op[3]] = C;
+ return bef;
+
+def gtir(before, op):
+ bef = before.copy();
+ C = 0 + int( op[1] > bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+def gtri(before, op):
+ bef = before.copy();
+ C = 0 + int( op[2] < bef[op[1]] );
+ bef[op[3]] = C;
+ return bef;
+def gtrr(before, op):
+ bef = before.copy();
+ C = 0 + int( bef[op[1]] > bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+
+def eqir(before, op):
+ bef = before.copy();
+ C = 0 + int( op[1] == bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+def eqri(before, op):
+ bef = before.copy();
+ C = 0 + int( op[2] == bef[op[1]] );
+ bef[op[3]] = C;
+ return bef;
+def eqrr(before, op):
+ bef = before.copy();
+ C = 0 + int( bef[op[1]] == bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+
+MatchFunctions = {};
+MatchFunctions.update({"addr":addr});
+MatchFunctions.update({"addi":addi});
+MatchFunctions.update({"mulr":mulr});
+MatchFunctions.update({"muli":muli});
+MatchFunctions.update({"banr":banr});
+MatchFunctions.update({"bani":bani});
+MatchFunctions.update({"borr":borr});
+MatchFunctions.update({"bori":bori});
+MatchFunctions.update({"setr":setr});
+MatchFunctions.update({"seti":seti});
+MatchFunctions.update({"gtir":gtir});
+MatchFunctions.update({"gtri":gtri});
+MatchFunctions.update({"gtrr":gtrr});
+MatchFunctions.update({"eqir":eqir});
+MatchFunctions.update({"eqri":eqri});
+MatchFunctions.update({"eqrr":eqrr});
+
+#end of day19 copy-paste
+###############################################
+
+f = open("input.txt",'r');
+Testing = False;
+#Testing = True;
+if Testing:
+ f.close();
+ f = open("testinput.txt",'r');
+
+ip = int(f.readline()[4:]);
+instructions = [];
+
+for l in f:
+ l = l.split();
+ i = [];
+ i.append(l[0]);
+ l_i = [int(x) for x in l[1:]];
+ i += l_i;
+ instructions.append(i);
+
+
+part1 = None;
+instr_lim = len(instructions);
+
+while True:
+ reg = [0,0,0,0,0,0];
+ reg[ip] = 0;
+ part1 = None;
+
+ while True:
+ if( reg[ip] >= instr_lim): break;
+ if( reg[ip] >= 28):
+ #print(reg);
+ part1 = int(reg[5]);
+ break;
+ instr = instructions[reg[ip]];
+ fun = MatchFunctions[instr[0]];
+ reg = fun(reg,instr);
+ reg[ip] += 1;
+
+ if part1 != None:
+ break;
+
+print("part 1 = ", part1, "(bruteforce)");
+
+#part2
+
+store1 = set(); #var ehich determines if the loop continues
+store5 = set(); #var checked against the reg0
+part1 = None;
+part2 = None;
+p2 = None;
+
+reg5 = 10678677;
+reg1 = 2**16;
+while True:
+ reg4 = reg1%256;
+ reg5 += reg4;
+ reg5 = ((reg5%2**24)*65899)%(2**24);
+
+ if reg1<256:
+ if not store5:
+ part1 = int(reg5);
+ if reg5 not in store5:
+ part2 = int(reg5);
+ store5.add(reg5);
+ #print("regs", reg1, reg5)
+ reg1 = reg5 | 2**16;
+ if reg1 in store1:
+ break;
+ store1.add(reg1);
+ reg5 = 10678677;
+ continue;
+
+ reg1 = reg1//256;
+
+print("part 1 = ", part1);
+print("part 2 = ", part2);
+
+#my input
+'''
+#ip 2
+seti 123 0 5
+bani 5 456 5
+eqri 5 72 5
+addr 5 2 2
+seti 0 0 2
+seti 0 4 5
+bori 5 65536 1
+seti 10678677 3 5
+bani 1 255 4
+addr 5 4 5
+bani 5 16777215 5
+muli 5 65899 5
+bani 5 16777215 5
+gtir 256 1 4
+addr 4 2 2
+addi 2 1 2
+seti 27 5 2
+seti 0 6 4
+addi 4 1 3
+muli 3 256 3
+gtrr 3 1 3
+addr 3 2 2
+addi 2 1 2
+seti 25 4 2
+addi 4 1 4
+seti 17 6 2
+setr 4 6 1
+seti 7 5 2
+eqrr 5 0 4
+addr 4 2 2
+seti 5 4 2
+'''