From 057d99fcea6a133f9d6ca43bf7de3ee55a8b341c Mon Sep 17 00:00:00 2001 From: dece Date: Mon, 16 Nov 2020 17:13:13 +0100 Subject: [PATCH] 2018 day 3 --- 2018/day3.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2018/grid.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 2019/grid.py | 2 +- 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 2018/day3.py create mode 100644 2018/grid.py diff --git a/2018/day3.py b/2018/day3.py new file mode 100644 index 0000000..eaeddb7 --- /dev/null +++ b/2018/day3.py @@ -0,0 +1,59 @@ +import re + +from grid import Grid + + +EX = [ + "#1 @ 1,3: 4x4", + "#2 @ 3,1: 4x4", + "#3 @ 5,5: 2x2", +] + + +def main(): + with open("day3.txt", "rt") as f: + lines = [line.rstrip() for line in f.readlines()] + + # Part 1 + g = Grid() + for line in lines: + ident, left, top, width, height = parse_line(line) + for i in range(int(width)): + for j in range(int(height)): + x = int(left) + i + y = int(top) + j + g.setv(x, y, g.getv(x, y) + 1) + n = get_overlaps(g) + print(n) + + # Part 2 + g = Grid() + over = [] + for line in lines: + ident, left, top, width, height = parse_line(line) + for i in range(int(width)): + for j in range(int(height)): + x = int(left) + i + y = int(top) + j + current_v = g.getv(x, y) + if current_v == None: + over.append(int(ident)) + continue + elif current_v == 0: + g.setv(x, y, int(ident)) + else: + over += [int(ident), current_v] + g.setv(x, y, None) + print(set(v for _, _, v in g.values_gen()).difference(set(over))) + +LINE_RE = re.compile(r"#(\d+) @ (\d+),(\d+): (\d+)x(\d+)") + +def parse_line(line): + match = LINE_RE.match(line) + return match.groups() + +def get_overlaps(grid): + return sum([v > 1 for _, _, v in grid.values_gen()]) + +if __name__ == "__main__": + main() diff --git a/2018/grid.py b/2018/grid.py new file mode 100644 index 0000000..87d7829 --- /dev/null +++ b/2018/grid.py @@ -0,0 +1,55 @@ +"""Generic 2D grid with a few helpers.""" + +from collections import defaultdict + + +class Grid: + + def __init__(self, value_factory=int, lines=None): + self.g = defaultdict(lambda: defaultdict(value_factory)) + if lines: + self.load(lines) + + def getv(self, x, y): + return self.g[y][x] + + def setv(self, x, y, value): + self.g[y][x] = value + + def load(self, lines, f=lambda v: v): + for y, line in enumerate(lines): + for x, c in enumerate(line.rstrip()): + self.g[y][x] = f(c) + + def values_gen(self): + for y, row in self.g.items(): + for x, v in row.items(): + yield (x, y, v) + + def near_objects(self, p): + """Return a dict of neighbor positions to values (U, L, D, R).""" + return {q: self.g[q[1]][q[0]] for q in Grid.near(p)} + + def dumb_print(self, f=lambda v: v): + for row in self.g.values(): + for x in row.values(): + print(f(x), end="") + print() + + def print_near(self, p, view_size=2): + """Print near values in an area of view_size. Works iff keys support addition.""" + for dy in range(-view_size, view_size + 1): + print("".join([ + self.g[p[1] + dy][p[0] + dx] + for dx in range(-view_size, view_size + 1) + ])) + + @staticmethod + def near(p): + """Return a tuple of neighbor positions (up, left, down, right).""" + return ( + (p[0] , p[1] - 1), + (p[0] + 1, p[1] ), + (p[0] , p[1] + 1), + (p[0] - 1, p[1] ), + ) diff --git a/2019/grid.py b/2019/grid.py index 2365fca..87d7829 100644 --- a/2019/grid.py +++ b/2019/grid.py @@ -12,7 +12,7 @@ class Grid: def getv(self, x, y): return self.g[y][x] - + def setv(self, x, y, value): self.g[y][x] = value