aoc-2018-python

Advent of Code 2018 Solutions in Python
git clone https://git.sinitax.com/sinitax/aoc-2018-python
Log | Files | Refs | README | sfeed.txt

solve.py (3864B)


      1import sys
      2sys.path.append("../common")
      3import aoc
      4from math import sqrt
      5
      6def parse_command(l):
      7    s = l.split(" ")
      8    args = [s[0]]
      9    args = args + [int(v) for v in s[1:]]
     10    return args
     11
     12data = aoc.data.split("\n")
     13
     14inspaddr = int(data[0][4:])
     15instructs = [parse_command(l) for l in data[1:] if len(l) != 0]
     16
     17register = [0 for x in range(inspaddr+1)]
     18
     19opmap = dict()
     20opmap["addr"] = lambda a, b : register[a] + register[b]
     21opmap["addi"] = lambda a, b : register[a] + b
     22opmap["mulr"] = lambda a, b : register[a] * register[b]
     23opmap["muli"] = lambda a, b : register[a] * b
     24opmap["banr"] = lambda a, b : register[a] & register[b]
     25opmap["bani"] = lambda a, b : register[a] & b
     26opmap["borr"] = lambda a, b : register[a] | register[b]
     27opmap["bori"] = lambda a, b : register[a] | b
     28opmap["setr"] = lambda a, b : register[a]
     29opmap["seti"] = lambda a, b : a
     30opmap["gtir"] = lambda a, b : 1 * (a > register[b])
     31opmap["gtri"] = lambda a, b : 1 * (register[a] > b)
     32opmap["gtrr"] = lambda a, b : 1 * (register[a] > register[b])
     33opmap["eqir"] = lambda a, b : 1 * (a == register[b])
     34opmap["eqri"] = lambda a, b : 1 * (register[a] == b)
     35opmap["eqrr"] = lambda a, b : 1 * (register[a] == register[b])
     36
     37def varname(v):
     38    return "R"+str(v)
     39
     40dismap = dict()
     41dismap["addr"] = lambda a, b : "%s + %s" % (varname(a), varname(b))
     42dismap["addi"] = lambda a, b : "%s + %d" % (varname(a), b)
     43dismap["mulr"] = lambda a, b : "%s * %s" % (varname(a), varname(b))
     44dismap["muli"] = lambda a, b : "%s * %d" % (varname(a), b)
     45dismap["banr"] = lambda a, b : "%s & %s" % (varname(a), varname(b))
     46dismap["bani"] = lambda a, b : "%s & %d" % (varname(a), b)
     47dismap["borr"] = lambda a, b : "%s | %s" % (varname(a), varname(b))
     48dismap["bori"] = lambda a, b : "%s | %d" % (varname(a), b)
     49dismap["setr"] = lambda a, b : "%s" % (varname(a))
     50dismap["seti"] = lambda a, b : "%d" % (a)
     51dismap["gtir"] = lambda a, b : "(%d > %s)" % (a, varname(b))
     52dismap["gtri"] = lambda a, b : "(%s > %d)" % (varname(a), b)
     53dismap["gtrr"] = lambda a, b : "(%s > %s)" % (varname(a), varname(b))
     54dismap["eqir"] = lambda a, b : "(%d == %s)" % (a, varname(b))
     55dismap["eqri"] = lambda a, b : "(%s == %d)" % (varname(a), b)
     56dismap["eqrr"] = lambda a, b : "(%s == %s)" % (varname(a), varname(b))
     57
     58def disassemble(s, e):
     59    for i in range(s, e):
     60        ins = instructs[i]
     61        aoc.debug(i ,":",varname(ins[3]),"=", dismap[ins[0]](ins[1], ins[2]))
     62    aoc.debug()
     63
     64def execute():
     65    global register, insptr
     66
     67    while register[inspaddr] < len(instructs):
     68        insptr = register[inspaddr]
     69        ins = instructs[insptr]
     70
     71        # execute command
     72        if len(register) <= ins[3]:
     73            register += [0 for x in range(ins[3] - len(register) + 1)]
     74        register[ins[3]] = opmap[ins[0]](ins[1], ins[2])
     75
     76        # part 1
     77        #if insptr == 13 and register[4] == 1:
     78        #    aoc.debug(register)
     79        #    return
     80
     81        # increment instruction pointer
     82        register[inspaddr] += 1
     83
     84def solve1(args):
     85    r0 = 1797184 # (first opportunity for comparison r1 and r0)
     86
     87    #disassemble(0, len(instructs))
     88    #execute()
     89
     90    return r0
     91
     92def solve2(args):
     93    r1 = 0
     94    candidates = list()
     95    while True:
     96        r4 = r1 | 65536 # flip 9th bit
     97        r1 = 3798839
     98        while True: # scan bytes of r4 and add them to r1 and multiply
     99            r5 = r4 & 255
    100            r1 += r5
    101            r1 = r1 & 16777215
    102            r1 *= 65899  # equals 1 00000001 01101011
    103            r1 = r1 & 16777215
    104            if r4 < 256:
    105                break
    106            r4 = int(r4/256) # bit shift 8 to the right
    107        if r1 not in candidates:
    108            candidates.append(r1)
    109        elif r1 == candidates[-1]:
    110            return candidates[-1]
    111
    112aoc.run(solve1, solve2, sols=[1797184, 11011493])