| import re | import re | ||||
| def parse(string): | |||||
| ns = [int(n) for n in re.findall(r'-?\d+', string)] | |||||
| memory = collections.defaultdict(int) | |||||
| memory.update(enumerate(ns)) | |||||
| return memory | |||||
| MODES = { | |||||
| '0': lambda ns, x, relbase: ns[x], | |||||
| '1': lambda ns, x, relbase: x, | |||||
| '2': lambda ns, x, relbase: ns[x + relbase], | |||||
| '0-special': lambda ns, x, relbase: x, | |||||
| '2-special': lambda ns, x, relbase: x + relbase, | |||||
| } | |||||
| def get_parameters(ns, pos, modes, N, writes, relbase): | def get_parameters(ns, pos, modes, N, writes, relbase): | ||||
| # paradox: return immediate mode to use positionally outside | # paradox: return immediate mode to use positionally outside | ||||
| modes[ord(c) - ord('a')] += '-special' | modes[ord(c) - ord('a')] += '-special' | ||||
| for mode, x in zip(modes, [ns[y] for y in range(pos, pos + N)]): | |||||
| yield { | |||||
| '0': lambda: ns[x], | |||||
| '1': lambda: x, | |||||
| '2': lambda: ns[x + relbase], | |||||
| '0-special': lambda: x, | |||||
| '2-special': lambda: x + relbase, | |||||
| }[mode]() | |||||
| yield pos + N | yield pos + N | ||||
| for i in range(N): | |||||
| mode, x = modes[i], ns[pos + i] | |||||
| yield MODES[mode](ns, x, relbase) | |||||
| def compute(ns, in_iter): | def compute(ns, in_iter): | ||||
| op = ns[pos] % 100 | op = ns[pos] % 100 | ||||
| # instructions stupidly say ABC referring to parameters 3, 2, 1 | # instructions stupidly say ABC referring to parameters 3, 2, 1 | ||||
| # we do a, b, c | # we do a, b, c | ||||
| modes = list(str(ns[pos] // 100).zfill(3)[::-1]) | |||||
| modes = list(str(ns[pos] // 100)[::-1] + '000') | |||||
| pos += 1 | pos += 1 | ||||
| if op == 1: | if op == 1: | ||||
| a, b, c, pos = consume(3, 'c') | |||||
| pos, a, b, c = consume(3, 'c') | |||||
| ns[c] = a + b | ns[c] = a + b | ||||
| elif op == 2: | elif op == 2: | ||||
| a, b, c, pos = consume(3, 'c') | |||||
| pos, a, b, c = consume(3, 'c') | |||||
| ns[c] = a * b | ns[c] = a * b | ||||
| elif op == 3: | elif op == 3: | ||||
| a, pos = consume(1, 'a') | |||||
| pos, a = consume(1, 'a') | |||||
| ns[a] = next(in_iter) | ns[a] = next(in_iter) | ||||
| elif op == 4: | elif op == 4: | ||||
| a, pos = consume(1) | |||||
| pos, a = consume(1) | |||||
| yield a | yield a | ||||
| elif op == 5: | elif op == 5: | ||||
| a, b, pos = consume(2) | |||||
| pos, a, b = consume(2) | |||||
| if a != 0: | if a != 0: | ||||
| pos = b | pos = b | ||||
| elif op == 6: | elif op == 6: | ||||
| a, b, pos = consume(2) | |||||
| pos, a, b = consume(2) | |||||
| if a == 0: | if a == 0: | ||||
| pos = b | pos = b | ||||
| elif op == 7: | elif op == 7: | ||||
| a, b, c, pos = consume(3, 'c') | |||||
| pos, a, b, c = consume(3, 'c') | |||||
| ns[c] = int(a < b) | ns[c] = int(a < b) | ||||
| elif op == 8: | elif op == 8: | ||||
| a, b, c, pos = consume(3, 'c') | |||||
| pos, a, b, c = consume(3, 'c') | |||||
| ns[c] = int(a == b) | ns[c] = int(a == b) | ||||
| elif op == 9: | elif op == 9: | ||||
| a, pos = consume(1) | |||||
| pos, a = consume(1) | |||||
| relbase += a | relbase += a | ||||
| elif op == 99: | elif op == 99: | ||||
| else: | else: | ||||
| raise RuntimeError(op) | raise RuntimeError(op) | ||||
| def parse(string): | |||||
| ns = [int(n) for n in re.findall(r'-?\d+', string)] | |||||
| memory = collections.defaultdict(int) | |||||
| memory.update(enumerate(ns)) | |||||
| return memory |