#advent of code 2018 #day 16 #part 1 and part 2 #when doing this puzzle I learned that I can make a list of functions and it just works #code could use a bit of clean up, #lots of multiple lines because of 16 functions #(I could save ~32 lines just by modifying the functions) #lots of work-arounds because I don't know to implement it efficently #but still, I got the results f = open("input.txt",'r'); Testing = False; #Testing = True; if Testing: f.close(); f = open("testinput.txt",'r'); input_part1 = []; input_part2 = []; sublist = []; for l in f: l = l.replace("\n",""); if (len(l) == 0): input_part1.append( sublist.copy() ); sublist = []; continue; elif (l == "###"): break; elif (len(l) < 20): sublist.append( [int(x) for x in l.split(" ")] ); elif (l[6] == ":"): sublist.append( eval(l[7:]) ); elif (l[5] == ":"): sublist.append( eval(l[7:]) ); ''' for i in input_part1: print(i[0], "\t", i[1], "\t", i[2], "\t") ''' for l in f: l = l.replace("\n",""); input_part2.append( [int(x) for x in l.split(" ")] ); ''' print(); print(); print(); for i in input_part2: print(i); ''' ###opcode functions def addr(before, op, aft): bef = before.copy(); C = bef[op[1]] + bef[op[2]]; bef[op[3]] = C; return bef; def addi(before, op, aft): bef = before.copy(); C = bef[op[1]] + op[2]; bef[op[3]] = C; return bef; def mulr(before, op, aft): bef = before.copy(); C = bef[op[1]] * bef[op[2]]; bef[op[3]] = C; return bef; def muli(before, op, aft): bef = before.copy(); C = bef[op[1]] * op[2]; bef[op[3]] = C; return bef; def banr(before, op, aft): bef = before.copy(); C = int(bef[op[1]] & bef[op[2]]); bef[op[3]] = C; return bef; def bani(before, op, aft): bef = before.copy(); C = int(bef[op[1]] & op[2]); bef[op[3]] = C; return bef; def borr(before, op, aft): bef = before.copy(); C = int(bef[op[1]] | bef[op[2]]); bef[op[3]] = C; return bef; def bori(before, op, aft): bef = before.copy(); C = int(bef[op[1]] | op[2]); bef[op[3]] = C; return bef; def setr(before, op, aft): bef = before.copy(); C = bef[op[1]]; bef[op[3]] = C; return bef; def seti(before, op, aft): bef = before.copy(); C = op[1]; bef[op[3]] = C; return bef; def gtir(before, op, aft): bef = before.copy(); C = 0 + int( op[1] > bef[op[2]] ); bef[op[3]] = C; return bef; def gtri(before, op, aft): bef = before.copy(); C = 0 + int( op[2] < bef[op[1]] ); bef[op[3]] = C; return bef; def gtrr(before, op, aft): bef = before.copy(); C = 0 + int( bef[op[1]] > bef[op[2]] ); bef[op[3]] = C; return bef; def eqir(before, op, aft): bef = before.copy(); C = 0 + int( op[1] == bef[op[2]] ); bef[op[3]] = C; return bef; def eqri(before, op, aft): bef = before.copy(); C = 0 + int( op[2] == bef[op[1]] ); bef[op[3]] = C; return bef; def eqrr(before, op, aft): bef = before.copy(); C = 0 + int( bef[op[1]] == bef[op[2]] ); bef[op[3]] = C; return bef; def threeormore(bef, op, aft): fun = 1; counter = 0; out = aft.copy(); counter += int( out == addr(bef,op,aft) ); counter += int( out == addi(bef,op,aft) ); counter += int( out == mulr(bef,op,aft) ); counter += int( out == muli(bef,op,aft) ); counter += int( out == banr(bef,op,aft) ); counter += int( out == bani(bef,op,aft) ); counter += int( out == borr(bef,op,aft) ); counter += int( out == bori(bef,op,aft) ); counter += int( out == setr(bef,op,aft) ); counter += int( out == seti(bef,op,aft) ); counter += int( out == gtir(bef,op,aft) ); counter += int( out == gtri(bef,op,aft) ); counter += int( out == gtrr(bef,op,aft) ); counter += int( out == eqir(bef,op,aft) ); counter += int( out == eqri(bef,op,aft) ); counter += int( out == eqrr(bef,op,aft) ); return counter; ''' if (counter >= 3): return 1; else: return 0; ''' part1 = 0; for sample in input_part1: before = sample[0]; instruction = sample[1]; after = sample[2]; part1 += 1*(threeormore(before, instruction, after ) >=3); print("part 1 = ", part1); #776 yoo high #588 correct #my mistake - misunderstood bitwise AND and bitwise OR #they dont return a boolean, just a normal integer #my function was int(bool(value)), which was reducing the correct value to 1 #identifying single matches ''' singles = []; doubles = []; triples = []; for sample in input_part1: before = sample[0]; instruction = sample[1]; after = sample[2]; if (threeormore(before, instruction, after ) == 1): singles.append(instruction[0]); if (threeormore(before, instruction, after ) == 2): doubles.append(instruction[0]); if (threeormore(before, instruction, after ) >= 3): triples.append(instruction[0]); #part1 += 1*(threeormore(before, instruction, after ) >=3); singles = list(dict.fromkeys(singles)); doubles = list(dict.fromkeys(doubles)); triples = list(dict.fromkeys(triples)); print("singles\t",len(singles), "\t", singles); print("doubles\t",len(doubles), "\t", doubles); print("triples\t",len(triples), "\t", triples); ''' def matchingfunctions(bef, op, aft): functionlist = ""; out = aft.copy(); functionlist += "addr"*( out == addr(bef,op,aft) ); functionlist += "addi"*( out == addi(bef,op,aft) ); functionlist += "mulr"*( out == mulr(bef,op,aft) ); functionlist += "muli"*( out == muli(bef,op,aft) ); functionlist += "banr"*( out == banr(bef,op,aft) ); functionlist += "bani"*( out == bani(bef,op,aft) ); functionlist += "borr"*( out == borr(bef,op,aft) ); functionlist += "bori"*( out == bori(bef,op,aft) ); functionlist += "setr"*( out == setr(bef,op,aft) ); functionlist += "seti"*( out == seti(bef,op,aft) ); functionlist += "gtir"*( out == gtir(bef,op,aft) ); functionlist += "gtri"*( out == gtri(bef,op,aft) ); functionlist += "gtrr"*( out == gtrr(bef,op,aft) ); functionlist += "eqir"*( out == eqir(bef,op,aft) ); functionlist += "eqri"*( out == eqri(bef,op,aft) ); functionlist += "eqrr"*( out == eqrr(bef,op,aft) ); return (op[0],functionlist); singles = []; doubles = []; triples = []; for sample in input_part1: before = sample[0]; instruction = sample[1]; after = sample[2]; if (threeormore(before, instruction, after ) == 1): singles.append(matchingfunctions(before, instruction, after )); if (threeormore(before, instruction, after ) == 2): doubles.append(matchingfunctions(before, instruction, after )); if (threeormore(before, instruction, after ) >= 3): triples.append(matchingfunctions(before, instruction, after )); #part1 += 1*(threeormore(before, instruction, after ) >=3); ''' print("singles\t",len(singles), "\t", singles); print("doubles\t",len(doubles), "\t", doubles); print("triples\t",len(triples), "\t", triples); ''' singles = list(dict.fromkeys(singles)); doubles = list(dict.fromkeys(doubles)); triples = list(dict.fromkeys(triples)); ''' for s in singles: print(s); print(); print(); for s in doubles: print(s); print(); print(); for s in triples: print(s); print(); print(); ''' PossibleFunctions = {}; total = singles + doubles + triples; for t in total: PossibleFunctions.update({t[0] : t[1]}); ''' for pf in PossibleFunctions: print(pf,"\t", PossibleFunctions[pf]); ''' IdentifiedFunctions = {}; while (len(IdentifiedFunctions) < 16): for found in IdentifiedFunctions: for possible in PossibleFunctions: if (len(PossibleFunctions[possible]) > 4 ): s = PossibleFunctions[possible]; s = s.replace(IdentifiedFunctions[found], ""); PossibleFunctions.update({possible : s}); for pf in PossibleFunctions: if (len(PossibleFunctions[pf]) == 4 ): IdentifiedFunctions.update({pf : PossibleFunctions[pf]}); ''' for pf in PossibleFunctions: print(pf,"\t", PossibleFunctions[pf]); input(); ''' ''' print(); print(); print(); print("Identified Functions"); for pf in IdentifiedFunctions: print(pf,"\t", IdentifiedFunctions[pf]); ''' 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}); for i in IdentifiedFunctions: MatchFunctions.update({i:MatchFunctions[IdentifiedFunctions[i]]}); ''' print(); print(); print(); print("Matched Functions"); for pf in MatchFunctions: print(pf,"\t", MatchFunctions[pf]); ''' reg = [0,0,0,0]; for i in input_part2: f_i = MatchFunctions[i[0]]; reg = f_i(reg, i, [] ); part2 = reg[0]; #print(reg); print("part 2 = ", part2);