From 6c517b47d9186b823dc2489569f666b14b5140b9 Mon Sep 17 00:00:00 2001 From: cupcakearmy Date: Tue, 7 Dec 2021 12:10:03 +0100 Subject: [PATCH] 05 --- 2021/05/README.md | 11 ++++ 2021/05/python/main.py | 141 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 2021/05/README.md create mode 100644 2021/05/python/main.py diff --git a/2021/05/README.md b/2021/05/README.md new file mode 100644 index 0000000..6078701 --- /dev/null +++ b/2021/05/README.md @@ -0,0 +1,11 @@ +# 05 + +Description + +
+ Solutions +
    +
  1. 5608
  2. +
  3. 20299
  4. +
+
diff --git a/2021/05/python/main.py b/2021/05/python/main.py new file mode 100644 index 0000000..093ea54 --- /dev/null +++ b/2021/05/python/main.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python + +from os.path import join, dirname +from typing import List + +# Day 05 + +# Common + + +def read_input(filename): + data = join(dirname(__file__), '..', filename) + with open(data) as f: + return f.read().strip() + + +class Point: + def __init__(self, x, y): + self.x = x + self.y = y + + def __repr__(self) -> str: + return f'({self.x},{self.y})' + + @staticmethod + def parse(raw: str): + x, y = raw.strip().split(',') + return Point(int(x), int(y)) + + +class Line: + def __init__(self, a: Point, b: Point): + self.a = a + self.b = b + + def is_straight(self) -> bool: + return self.a.x == self.b.x or self.a.y == self.b.y + + def is_diagonal(self) -> bool: + return abs(self.a.x - self.b.x) == abs(self.a.y - self.b.y) + + def get_points(self) -> List[Point]: + if self.is_straight(): + if self.a.x == self.b.x: + return [ + Point(self.a.x, y) for y + in range(min(self.a.y, self.b.y), max(self.a.y, self.b.y) + 1) + ] + else: + return [ + Point(x, self.a.y) for x + in range(min(self.a.x, self.b.x), max(self.a.x, self.b.x) + 1) + ] + else: + dx = self.a.x - self.b.x + dy = self.a.y - self.b.y + sign_x = 1 if dx < 0 else -1 + sign_y = 1 if dy < 0 else -1 + return [ + Point(self.a.x + sign_x * i, self.a.y + sign_y * i) + for i in range(abs(dx) + 1) + ] + + def __repr__(self) -> str: + return f'{self.a} → {self.b}' + + @staticmethod + def parse(raw: str): + a, b = raw.strip().split('->') + return Line(Point.parse(a), Point.parse(b)) + + +class Scan: + def __init__(self, lines: List[Line]): + self.lines = lines + + def keep_straight(self): + self.lines = [line for line in self.lines if line.is_straight()] + + def keep_straight_and_diagonal(self): + self.lines = [ + line for line in self.lines + if line.is_straight() or line.is_diagonal() + ] + + def matrix(self) -> List[List[int]]: + x_max = max(max(line.a.x, line.b.x) for line in self.lines) + y_max = max(max(line.a.y, line.b.y) for line in self.lines) + matrix = [ + [0 for _ in range(x_max + 1)] + for _ in range(y_max + 1) + ] + for line in self.lines: + for point in line.get_points(): + matrix[point.y][point.x] += 1 + return matrix + + def plot(self) -> str: + output = '\n'.join([ + ' '.join(str(x) for x in row) + for row in self.matrix() + ]) + return output.replace('0', '.') + + def danger(self) -> int: + matrix = self.matrix() + return sum( + sum(1 for x in row if x > 1) + for row in matrix + ) + + @ staticmethod + def parse(raw: str): + return Scan([Line.parse(line) for line in raw.strip().split('\n')]) + + +test = read_input('test.txt') +data = read_input('input.txt') + +# 1 +print('1.') +scan = Scan.parse(test) +scan.keep_straight() +print(scan.plot()) +print('Test: ', scan.danger()) + +scan = Scan.parse(data) +scan.keep_straight() +print('Real: ', scan.danger()) + +# 2 +print('\n2.') + +scan = Scan.parse(test) +scan.keep_straight_and_diagonal() +print(scan.plot()) +print('Test: ', scan.danger()) + +scan = Scan.parse(data) +scan.keep_straight_and_diagonal() +print('Real: ', scan.danger())