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 (3233B)


      1import sys
      2sys.path.append("../common")
      3import aoc
      4
      5def parse_log(ls):
      6    data = list()
      7    before = [int(v) for v in ls[0].split("[")[1].split("]")[0].split(",")]
      8    ins = [int(v) for v in ls[1].split(" ")]
      9    after = [int(v) for v in ls[2].split("[")[1].split("]")[0].split(",")]
     10    return (before, ins, after)
     11
     12inslog = []
     13data = aoc.data.split("\n")
     14progsec = None
     15for i in range(0, len(data), 4):
     16    if data[i] == "\n":
     17        progsec = i
     18        break
     19    inslog.append(parse_log(data[i:i+4]))
     20
     21register = list()
     22
     23opmap = dict()
     24opmap["addr"] = lambda a, b : register[a] + register[b]
     25opmap["addi"] = lambda a, b : register[a] + b
     26opmap["mulr"] = lambda a, b : register[a] * register[b]
     27opmap["muli"] = lambda a, b : register[a] * b
     28opmap["banr"] = lambda a, b : register[a] & register[b]
     29opmap["bani"] = lambda a, b : register[a] & b
     30opmap["borr"] = lambda a, b : register[a] | register[b]
     31opmap["bori"] = lambda a, b : register[a] | b
     32opmap["setr"] = lambda a, b : register[a]
     33opmap["seti"] = lambda a, b : a
     34opmap["gtir"] = lambda a, b : 1 * (a > register[b])
     35opmap["gtri"] = lambda a, b : 1 * (register[a] > b)
     36opmap["gtrr"] = lambda a, b : 1 * (register[a] > register[b])
     37opmap["eqir"] = lambda a, b : 1 * (a == register[b])
     38opmap["eqri"] = lambda a, b : 1 * (register[a] == b)
     39opmap["eqrr"] = lambda a, b : 1 * (register[a] == register[b])
     40
     41def get_possible(ins):
     42    global register
     43    sregister = register[:]
     44    before = ins[0]
     45    after = ins[2]
     46    register = before
     47    a = ins[1][1]
     48    b = ins[1][2]
     49    c = ins[1][3]
     50    ops = list(opmap.values())
     51    possibles = list()
     52    for i in range(len(ops)):
     53        op = ops[i]
     54        res = None
     55        try:
     56            res = op(a, b)
     57        except:
     58            continue
     59        if res == after[c]:
     60            possibles.append(i)
     61    register = sregister
     62    return possibles
     63
     64def solve1(args):
     65    global register
     66    uncertain = 0
     67    for ins in inslog:
     68        if len(get_possible(ins)) >= 3:
     69            uncertain += 1
     70    return uncertain
     71
     72def solve2(args):
     73    possible = dict()
     74    for ins in inslog:
     75        o = ins[1][0]
     76        if o in possible:
     77            possible[o] = [op for op in get_possible(ins) if op in possible[o]]
     78        else:
     79            possible[o] = get_possible(ins)
     80
     81    certain = False
     82    while not certain:
     83        singles = [p[0] for p in possible.values() if len(p) == 1]
     84        for p in possible:
     85            if len(possible[p]) != 1:
     86                possible[p] = [v for v in possible[p] if v not in singles]
     87
     88        certain = True
     89        for p in possible.values():
     90            if len(p) != 1:
     91                certain = False
     92                break
     93
     94    ntrans = dict()
     95    for p in possible: # flatten
     96        ntrans[p] = possible[p][0]
     97
     98    for i in range(progsec, len(data)): # execute program
     99        l = data[i]
    100        if l == "\n": continue
    101        cmd = [int(v) for v in l.split(" ")]
    102        while len(register)-1 < cmd[3]:
    103            register.append(0)
    104
    105        register[cmd[3]] = list(opmap.values())[ntrans[cmd[0]]](cmd[1], cmd[2])
    106
    107    return register[0]
    108
    109aoc.run(solve1, solve2, sols=[531, 649])