From 87fdcce19734780f36aa8c94b17dd298e6b12413 Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Wed, 16 Dec 2020 03:21:17 +0100 Subject: [PATCH] python: Submit Python solutions --- python/day07.py | 48 +++++++++++++++++++ python/day09-a.py | 22 +++++++++ python/day09-b.py | 22 +++++++++ python/day10.py | 38 +++++++++++++++ python/day11.py | 118 ++++++++++++++++++++++++++++++++++++++++++++++ python/day13.py | 48 +++++++++++++++++++ python/day14.py | 55 +++++++++++++++++++++ 7 files changed, 351 insertions(+) create mode 100644 python/day07.py create mode 100644 python/day09-a.py create mode 100644 python/day09-b.py create mode 100644 python/day10.py create mode 100644 python/day11.py create mode 100644 python/day13.py create mode 100644 python/day14.py diff --git a/python/day07.py b/python/day07.py new file mode 100644 index 0000000..ecd29da --- /dev/null +++ b/python/day07.py @@ -0,0 +1,48 @@ +import fileinput +import re +from collections import defaultdict + +network = {} +reverse = defaultdict(list) + +for line in fileinput.input(): + parent, children = line.strip().split(" contain ") + parent = parent[:-5] + children = children.rstrip(".").split(", ") + children = [ + child.rstrip("s")[:-4].split(" ", 1) + for child in children + if "no other" not in child + ] + children = [(int(n), c) for n, c in children] + + network[parent] = children + for n, child in children: + reverse[child].append((n, parent)) + +reverse = dict(reverse) + +shiny_gold_bags = set() +stack = ["shiny gold"] +while stack: + color = stack.pop() + if color not in reverse: + continue + for _, parent in reverse[color]: + stack.append(parent) + shiny_gold_bags.add(parent) + +print("part 1:", len(shiny_gold_bags)) + +part2 = 0 +stack = [(1, "shiny gold")] +while stack: + n, color = stack.pop() + part2 += n + + children = network[color] + for m, child in children: + stack.append((n * m, child)) +part2 -= 1 + +print("part 2:", part2) diff --git a/python/day09-a.py b/python/day09-a.py new file mode 100644 index 0000000..3fb0ccd --- /dev/null +++ b/python/day09-a.py @@ -0,0 +1,22 @@ +import fileinput +import itertools + +N = 25 + +numbers = [] +for line in fileinput.input(): + numbers.append(int(line)) + +for i in range(N, len(numbers)): + found = False + for j in numbers[i - N:i]: + for k in numbers[i - N:i]: + if j == k: + continue + if j + k == numbers[i]: + found = True + if not found: + print(numbers[i]) + break + + diff --git a/python/day09-b.py b/python/day09-b.py new file mode 100644 index 0000000..f6d441d --- /dev/null +++ b/python/day09-b.py @@ -0,0 +1,22 @@ +import fileinput +import itertools +import sys + +N = 25 + +numbers = [] +for line in fileinput.input(): + numbers.append(int(line)) + +for i in range(N, len(numbers)): + target = 25918798 + #target=127 + for j in range(i - N,i): + for k in range(j+ 1, i): + nn = numbers[j:k] + if sum(nn) == target: + print(max(nn) + min(nn)) + sys.exit(0) + + + diff --git a/python/day10.py b/python/day10.py new file mode 100644 index 0000000..bd46b75 --- /dev/null +++ b/python/day10.py @@ -0,0 +1,38 @@ +import fileinput +import itertools +from collections import deque + +adapters = [0] +for line in fileinput.input(): + adapters.append(int(line)) +adapters.sort() +adapters.append(adapters[-1] + 3) + +one = 0 +three = 0 + +for (fr, to) in zip(adapters[:-1], adapters[1:]): + if to - fr == 1: + one += 1 + elif to - fr == 3: + three += 1 + print(fr, to) + +print(one, three, one * three) +paths = [0] * len(adapters) +paths[0] = 1 + +ways = 1 +for i, value in enumerate(adapters[:-1]): + try: + if adapters[i + 1] <= value + 3: + paths[i + 1] += paths[i] + if adapters[i + 2] <= value + 3: + paths[i + 2] += paths[i] + if adapters[i + 3] <= value + 3: + paths[i + 3] += paths[i] + except IndexError: + pass + +print(paths) +print(paths[-1]) diff --git a/python/day11.py b/python/day11.py new file mode 100644 index 0000000..7128d78 --- /dev/null +++ b/python/day11.py @@ -0,0 +1,118 @@ +import fileinput +from pprint import pprint +from copy import deepcopy + +layout = [] +for line in fileinput.input(): + if line.strip(): + layout.append(list(line.strip())) + +part1 = -1 +old_layout = deepcopy(layout) +row_length = len(old_layout[0]) + +while True: + new_layout = [[None] * len(row) for row in old_layout] + for y in range(len(old_layout)): + for x in range(len(old_layout[0])): + if old_layout[y][x] == ".": + new_layout[y][x] = old_layout[y][x] + continue + + count = sum( + ( + x >= 1 and old_layout[y][x - 1] == "#", + x < row_length - 1 and old_layout[y][x + 1] == "#", + ) + ) + + if y >= 1: + count += sum( + ( + x >= 1 and old_layout[y - 1][x - 1] == "#", + old_layout[y - 1][x] == "#", + x < row_length - 1 and old_layout[y - 1][x + 1] == "#", + ) + ) + + if y < len(layout) - 1: + count += sum( + ( + x >= 1 and old_layout[y + 1][x - 1] == "#", + old_layout[y + 1][x] == "#", + x < row_length - 1 and old_layout[y + 1][x + 1] == "#", + ) + ) + + if count == 0: + new_layout[y][x] = "#" + elif count >= 4: + new_layout[y][x] = "L" + else: + new_layout[y][x] = old_layout[y][x] + + new_part1 = sum(sum(s == "#" for s in row) for row in new_layout) + if part1 == new_part1: + break + part1 = new_part1 + + old_layout = new_layout + +print(part1) + + +part2 = -1 +old_layout = deepcopy(layout) + + +def get(x, y, dx, dy): + try: + x += dx + y += dy + while old_layout[y][x] == ".": + if x < 0 or y < 0: + raise IndexError + x += dx + y += dy + except: + return "." + + return old_layout[y][x] + + +while True: + new_layout = [[None] * len(row) for row in old_layout] + for y in range(1, len(old_layout) - 1): + for x in range(1, len(old_layout[0]) - 1): + if old_layout[y][x] == ".": + new_layout[y][x] = old_layout[y][x] + continue + + count = sum( + ( + get(x, y, -1, -1) == "#", + get(x, y, -1, 0) == "#", + get(x, y, -1, 1) == "#", + get(x, y, 0, -1) == "#", + get(x, y, 0, 1) == "#", + get(x, y, 1, -1) == "#", + get(x, y, 1, 0) == "#", + get(x, y, 1, 1) == "#", + ) + ) + + if count == 0: + new_layout[y][x] = "#" + elif count >= 5: + new_layout[y][x] = "L" + else: + new_layout[y][x] = old_layout[y][x] + + new_part2 = sum(sum(s == "#" for s in row) for row in new_layout) + if part2 == new_part2: + break + part2 = new_part2 + + old_layout = new_layout + +print(part2) diff --git a/python/day13.py b/python/day13.py new file mode 100644 index 0000000..f49c284 --- /dev/null +++ b/python/day13.py @@ -0,0 +1,48 @@ +import fileinput + +input = fileinput.input() + +arrival = int(next(input)) +buses = [None if bus == "x" else int(bus) for bus in next(input).split(",")] +print(arrival, buses) + +remainders = [-(arrival % (-bus)) if bus else float("inf") for bus in buses] +print(remainders) + +print( + "Part 1:", + min(enumerate(buses), key=lambda x: remainders[x[0]])[1] * min(remainders), +) + +def combine(a_period, a_offset, b_period, b_offset): + gcd, s, _ = egcd(a_period, b_period) + diff = a_offset - b_offset + diff_quot, dif_rem = divmod(diff, gcd) + assert(dif_rem == 0) + + combined_period = a_period // gcd * b_period + combined_offset = (a_offset - s * diff_quot * a_period) % combined_period + return combined_period, combined_offset + +def egcd(a, b): + r_, r = a, b + s_, s = 1, 0 + t_, t = 0, 1 + while r: + quot, rem = divmod(r_, r) + r_, r = r, rem + s_, s = s, (s_ - quot * s) + t_, t = t, (t_ - quot * t) + return r_, s_, t_ + +period = 1 +offset = 0 + +for i, bus in enumerate(buses): + if bus is None: + continue + + period, offset = combine(period, offset, bus, i) + print(i, bus, period, offset) + +print(-offset % period) diff --git a/python/day14.py b/python/day14.py new file mode 100644 index 0000000..b736e9a --- /dev/null +++ b/python/day14.py @@ -0,0 +1,55 @@ +import fileinput +from pprint import pprint +from typing import List + +mem = {} +for line in fileinput.input(): + l, r = line.strip().split(" = ") + if l == "mask": + and_mask = int(r.replace("X", "1"), base=2) + or_mask = int(r.replace("X", "0"), base=2) + else: + value = int(r) + value &= and_mask + value |= or_mask + mem[int(l[4:-1])] = value + +print(sum(mem.values())) + +def recurse(s: str) -> List[str]: + x = s.find("X") + if x == -1: + return [s] + + s0 = s[:x] + '0' + s[x + 1:] + s1 = s[:x] + '1' + s[x + 1:] + + return [*recurse(s0), *recurse(s1)] + +mem = {} +for line in fileinput.input(): + l, r = line.strip().split(" = ") + + if l == "mask": + mask = r + or_mask = int(r.replace("X", "0"), base=2) + + floatings = recurse(r.replace("0", "_").replace("1", "_")) + and_masks = [int(v.replace("_", "1"), 2) for v in floatings] + or_masks = [int(v.replace("_", "0"), 2) for v in floatings] + + assert(len(and_masks) == 2 ** r.count("X")) + assert(len(or_masks) == 2 ** r.count("X")) + else: + orig_address = int(l[4:-1]) + orig_address |= or_mask + + for (and_, or_) in zip(and_masks, or_masks): + address = orig_address + address &= and_ + address |= or_ + mem[address] = int(r) + assert(address >= 0) + +assert(not [k for k in mem.keys() if k < 0]) +print(sum(mem.values()))