diff options
Diffstat (limited to '2018/aoc2018-d21.py')
-rw-r--r-- | 2018/aoc2018-d21.py | 253 |
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 +''' |