def main(file): print("RUNNING", file) grid = set() for line in aocutils.readlines(file): parts = aocutils.multisplit(line, [' x=', '..', ',y=', '..', ',z=', '..']) action = parts[0] x0, x1, y0, y1, z0, z1 = [int(a) for a in parts[1:]] assert x0 <= x1 assert y0 <= y1 assert z0 <= z1 x0 = max(x0, -50) y0 = max(y0, -50) z0 = max(z0, -50) x1 = min(x1, 50) y1 = min(y1, 50) z1 = min(z1, 50) for x in range(x0, x1 + 1): for y in range(y0, y1 + 1): for z in range(z0, z1 + 1): if action == 'on': grid.add((x, y, z)) else: grid.discard((x, y, z)) print(len(grid))
def main(file): print("RUNNING", file) lines = list(aocutils.readlines(file)) line = lines[0] numbers = line.split(",") numbers = [int(n) for n in numbers] t = 1 prev = None times = dict() while True: if t <= len(numbers): current = numbers[t - 1] else: ts = times.get(prev, None) if ts is None: current = 0 else: current = t - ts - 1 if t == 2020: print("2020: ", current) if t == 30000000: print("30,000,000:", current) break if prev is not None: # print(t - 1, prev) times[prev] = t - 1 prev = current t += 1
def main(file): print("RUNNING", file) map = [] for line in aocutils.readlines(file): row = [] for c in line: if c == 'L': row.append(True) else: row.append(None) map.append(row) # print_map(map) while True: changed = list(find_changed(map)) if not changed: break for a, b, val in changed: map[a][b] = val # print_map(map) count = 0 for row in map: for v in row: if v: count += 1 print(count)
def main(file): print("RUNNING", file) line = list(aocutils.readlines(file))[0] positions = [int(x) for x in line.split(',')] sortedp = sorted(positions) p0 = sortedp[len(sortedp) // 2] p1 = p0 + 1 c0 = total_fuel_cost(p0, positions) c1 = total_fuel_cost(p1, positions) if c0 > c1: start = p1 cost = c1 dir = 1 else: start = p0 cost = c0 dir = -1 pos = start while True: nextp = pos + dir nextc = total_fuel_cost(nextp, positions) if nextc > cost: break pos = nextp cost = nextc print(pos) print(cost)
def main(file): print("RUNNING", file) zeros = None ones = None for line in aocutils.readlines(file): if zeros is None: zeros = [0 for _ in line] ones = [0 for _ in line] for i, bit in enumerate(line): if bit == '1': ones[i] += 1 else: zeros[i] += 1 gamma = 0 epsilon = 0 for i in range(len(ones)): gamma = gamma << 1 epsilon = epsilon << 1 if ones[i] > zeros[i]: gamma |= 1 else: epsilon |= 1 print(gamma, epsilon) print(gamma * epsilon)
def main(file): print("RUNNING", file) result = 0 for line in aocutils.readlines(file): val = evaluate(line) result += val print(result)
def main(file): print("RUNNING", file) incomplete_score = [] for line in aocutils.readlines(file): stack = [] corrupted = False for char in line: if char == '(': stack.append(')') elif char == '[': stack.append(']') elif char == '{': stack.append('}') elif char == '<': stack.append('>') else: expected = stack.pop() if char != expected: corrupted = True break if corrupted: continue line_score = 0 while stack: expected = stack.pop() line_score = line_score * 5 + scoring[expected] incomplete_score.append(line_score) incomplete_score.sort() print(incomplete_score[len(incomplete_score) // 2])
def main(file): print("RUNNING", file) map = [] for line in aocutils.readlines(file): map.append([int(x) for x in line]) flashes = 0 all_of_them = len(map) * len(map[0]) for step in range(1, 10_000): flashed = set() for y in range(len(map)): for x in range(len(map[0])): map[y][x] += 1 prev_flashes = -1 while flashes != prev_flashes: prev_flashes = flashes for y in range(len(map)): for x in range(len(map[0])): if map[y][x] > 9 and (y, x) not in flashed: flashed.add((y, x)) flashes += 1 for y1, x1 in neighbors(map, y, x): map[y1][x1] += 1 for y, x in flashed: map[y][x] = 0 if len(flashed) == all_of_them: print(step) break
def main(file): print("RUNNING", file) on_actions = defaultdict(int) off_actions = defaultdict(int) total = 0 for line in aocutils.readlines(file): parts = aocutils.multisplit(line, [' x=', '..', ',y=', '..', ',z=', '..']) action_type = parts[0] x0, x1, y0, y1, z0, z1 = [int(a) for a in parts[1:]] assert x0 <= x1 assert y0 <= y1 assert z0 <= z1 cuboid = Cuboid(x0, x1, y0, y1, z0, z1) # Turn off all cubes inside the cuboid by doing # the inverse of all actions so far, but only in the # intersection with the cuboid prev_actions = [] for k, v in on_actions.items(): for _ in range(v): prev_actions.append(('on', k)) for k, v in off_actions.items(): for _ in range(v): prev_actions.append(('off', k)) for prev_action_type, c in prev_actions: if prev_action_type == 'on': if overlap_cuboid := overlap(c, cuboid): if not try_remove_cuboid(on_actions, overlap_cuboid): off_actions[overlap_cuboid] += 1 total -= size(overlap_cuboid) elif prev_action_type == 'off': if overlap_cuboid := overlap(c, cuboid): if not try_remove_cuboid(off_actions, overlap_cuboid): on_actions[overlap_cuboid] += 1 total += size(overlap_cuboid)
def main(file): print("RUNNING", file) program = [] for line in aocutils.readlines(file): inst, a = line.split(" ") a = int(a) program.append((inst, a)) acc, run = run_program(program) for i in run: old = program[i] prev, num = old if prev == "nop": replace = ("jmp", num) program[i] = replace elif prev == "jmp": replace = ("nop", num) program[i] = replace else: continue try: run_program(program) program[i] = old except Done as e: print(e.acc) return
def main(file): print("RUNNING", file) memory = {} masks = [] for line in aocutils.readlines(file): if line.startswith("mask"): pattern = line.split(" = ")[1] masks = [Mask()] for c in pattern: if c == "X": new_masks = [] for mask in masks: new_masks.append(mask.both()) masks.extend(new_masks) elif c == "1": for mask in masks: mask.push_force1() elif c == "0": for mask in masks: mask.push_unchanged() else: assert False else: parts = aocutils.multisplit(line, ["[", "]", " = "]) address = int(parts[1]) value = int(parts[-1]) for mask in masks: a = mask.apply(address) memory[a] = value print(sum(memory.values()))
def main(file): print("RUNNING", file) # 10X # (0b111 & 0b101) | 0b100 = 0x101 # (0b000 & 0b101) | 0b100 = 0x100 memory = {} and_mask = 0 or_mask = 0 for line in aocutils.readlines(file): if line.startswith("mask"): pattern = line.split(" = ")[1] and_mask = 0 or_mask = 0 for c in pattern: and_mask = and_mask << 1 or_mask = or_mask << 1 if c == "X": and_mask |= 1 elif c == "1": and_mask |= 1 or_mask |= 1 elif c == "0": pass else: assert False else: parts = aocutils.multisplit(line, ["[", "]", " = "]) address = int(parts[1]) value = int(parts[-1]) write_value = (value & and_mask) | or_mask memory[address] = write_value print(sum(memory.values()))
def main(file): print("RUNNING", file) lookup = defaultdict(set) for line in aocutils.readlines(file): line = line.strip() line = line.strip(".") bag, rest = line.split(" contain ") bag = bag[:-1] if rest != "no other bags": for x in rest.split(", "): c, name = x.split(" ", 1) c = int(c) if c != 1: name = name[:-1] lookup[bag].add(name) find = "shiny gold bag" found = set() changed = True while changed: count = len(found) for bag in lookup.keys(): contents = lookup[bag] if find in contents or any(c for c in contents if c in found): found.add(bag) changed = count != len(found) print(found) print(len(found))
def main(file): print("RUNNING", file) program = [] for line in aocutils.readlines(file): inst, a = line.split(" ") a = int(a) program.append((inst, a)) acc = 0 run = set() i = 0 while True: if i in run: break run.add(i) inst, num = program[i] if inst == "nop": i += 1 elif inst == "acc": acc += num i += 1 elif inst == "jmp": i += num else: assert False print(acc)
def main(file): print("RUNNING", file) actions = [] total = 0 for line in aocutils.readlines(file): parts = aocutils.multisplit(line, [' x=', '..', ',y=', '..', ',z=', '..']) action_type = parts[0] x0, x1, y0, y1, z0, z1 = [int(a) for a in parts[1:]] assert x0 <= x1 assert y0 <= y1 assert z0 <= z1 cuboid = Cuboid(x0, x1, y0, y1, z0, z1) # Turn off all cubes inside the cuboid by doing # the inverse of all actions so far, but only in the # intersection with the cuboid new_actions = [] for prev_action_type, c in actions: if prev_action_type == 'on': if overlap_cuboid := overlap(c, cuboid): new_actions.append(('off', overlap_cuboid)) total -= size(overlap_cuboid) elif prev_action_type == 'off': if overlap_cuboid := overlap(c, cuboid): new_actions.append(('on', overlap_cuboid)) total += size(overlap_cuboid)
def main(file): print("RUNNING", file) total = 0 for line in aocutils.readlines(file): line_split = line.split(' | ') signal_digits = [ ''.join(sorted(digit)) for digit in line_split[0].split(' ') ] output_digits = [ ''.join(sorted(digit)) for digit in line_split[1].split(' ') ] all_digits = signal_digits + output_digits mappings = {} # Assign initial choices based on number of segments for digit in all_digits: digit = ''.join(sorted(digit)) if digit in mappings: continue segments = len(digit) if segments == 2: possible_choices = {1} elif segments == 3: possible_choices = {7} elif segments == 4: possible_choices = {4} elif segments == 7: possible_choices = {8} elif segments == 5: possible_choices = {2, 3, 5} elif segments == 6: possible_choices = {0, 6, 9} else: assert False mappings[digit] = possible_choices # Reduce choices for uncertain mappings based on amount of segments shared with already known mappings while True: if all(len(mappings[d]) == 1 for d in output_digits): break for digit in all_digits: possible_choices = mappings[digit] if len(possible_choices) == 1: continue for other_digit, other_digit_choices in mappings.items(): if digit == other_digit: continue if len(other_digit_choices) == 1: other_mapped_to = list(other_digit_choices)[0] for assumed in list(possible_choices): expected_shared = len( set(digit).intersection(set(other_digit))) if shared_segments[ assumed, other_mapped_to] != expected_shared: # The amount of shared segments does not match assumed, it is not a valid choice mappings[digit].discard(assumed) total += int(''.join( [str(list(mappings[x])[0]) for x in output_digits])) print("total", total)
def main_part1(file): print("RUNNING", "part1", file) numbers = [json.loads(line) for line in aocutils.readlines(file)] curr = make_number(numbers[0]) for n in numbers[1:]: curr = Pair(curr, make_number(n)) reduce(curr) print(curr.magnitude())
def main(): entries = [int(x) for x in aocutils.readlines("input.txt")] data = set(entries) for a in entries: b = 2020 - a if b in data: print(a, '+', b, '=', a + b) print(a, '*', b, '=', a * b)
def window_sums(file): b = None c = None for line in aocutils.readlines(file): a = int(line) if b is not None and c is not None: yield a + b + c b, c = a, b
def main(file): print("RUNNING", file) cnt = 0 for line in aocutils.readlines(file): out = line.split(' | ')[1] for digit in out.split(' '): if len(digit) in [2, 3, 4, 7]: cnt += 1 print(cnt)
def main_part1(file): print("RUNNING", "part1", file) numbers = [json.loads(line) for line in aocutils.readlines(file)] curr = numbers[0] for n in numbers[1:]: curr = [curr, n] reduce(curr) # print(curr) print(magnitude(curr))
def main_part2(file): print("RUNNING", "part2", file) numbers = [json.loads(line) for line in aocutils.readlines(file)] max_magnitude = 0 for i, n1 in enumerate(numbers): for j, n2 in enumerate(numbers): if i != j: max_magnitude = max(max_magnitude, magnitude(add(n1, n2))) print(max_magnitude)
def main(file): print("RUNNING", file) neighbors.clear() for line in aocutils.readlines(file): a, b = line.split('-') neighbors[a].append(b) neighbors[b].append(a) state = State([]) visit(state, 'start') print(state.paths)
def main(file): print("RUNNING", file) pub1, pub2 = list(aocutils.readlines(file)) pub1 = int(pub1) pub2 = int(pub2) priv1 = reverse_loop_size(7, pub1) priv2 = reverse_loop_size(7, pub2) x = transform_subject(pub1, priv2) y = transform_subject(pub2, priv1) assert x == y print(x)
def main(file): neighbors.clear() paths.clear() print("RUNNING", file) for line in aocutils.readlines(file): a, b = line.split('-') neighbors[a].append(b) neighbors[b].append(a) visited = list() visit('start', visited) print(len(paths))
def main(file): print("RUNNING", file) cnt = 0 prev = None for line in aocutils.readlines(file): a = int(line) if prev is not None: if a > prev: cnt += 1 prev = a print(cnt)
def main(file): print("RUNNING", file) map = [] for line in aocutils.readlines(file): map.append(([int(x) for x in line])) result = [] for y, row in enumerate(map): for x, v in enumerate(row): if is_low_point(map, y, x): result.append(basin_size(map, y, x)) result.sort(reverse=True) print(result[0] * result[1] * result[2])
def main(file): print("RUNNING", file) lines = list(aocutils.readlines(file)) buses = [] for offset, number in enumerate(lines[1].split(",")): if number != 'x': buses.append((int(number), offset)) bus_period, offset = buses[0] first_t, period = bus_period - offset, bus_period for bus in buses[1:]: first_t, period = period_of(bus, candidates_from_period(first_t, period)) print(first_t)
def main(file): print("RUNNING", file) lines = [int(l) for l in aocutils.readlines(file)] lines.sort() lines.append(lines[-1] + 3) diffs = defaultdict(lambda: 0) jole = 0 for l in lines: diff = l - jole jole = l diffs[diff] += 1 print(dict(diffs)) print(diffs[1] * diffs[3])
def main(file, window_size): print("RUNNING", file) numbers = list(int(x) for x in aocutils.readlines(file)) for i in range(window_size, len(numbers)): n = numbers[i] recent = numbers[i - window_size:i] ok = False for p in recent: q = (n - p) if q in recent: ok = True break if not ok: print(n)