summaryrefslogtreecommitdiffstats
path: root/day9/__init__.py
blob: afa44aab105f8e05a6051adee63929f5c20d750f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# -*- coding: utf-8 -*-
from abc import ABC
from copy import copy
from dataclasses import dataclass
from typing import Tuple, Iterator, List

from aoc import BaseAssignment


@dataclass
class Coordinate:
    x: int
    y: int

    def __hash__(self):
        return tuple([self.x, self.y]).__hash__()

    def __sub__(self, other: "Coordinate"):
        return Coordinate(self.x - other.x, self.y - other.y)

    @property
    def polarity_x(self):
        try:
            return abs(self.x) / self.x
        except ZeroDivisionError:
            return 0

    @property
    def polarity_y(self):
        try:
            return abs(self.y) / self.y
        except ZeroDivisionError:
            return 0


class Assignment(BaseAssignment, ABC):
    def parse_line(self, item: str) -> Tuple[str, int]:
        direction, amount = item.split(" ")
        return direction, int(amount)

    def move(self, direction: str, amount: int):
        pass

    @staticmethod
    def next_head(head: Coordinate, direction: str):
        match direction:
            case "R":
                head.x += 1
            case "L":
                head.x -= 1
            case "U":
                head.y += 1
            case "D":
                head.y -= 1

    @staticmethod
    def next_tail(head: Coordinate, tail: Coordinate):
        delta = head - tail

        if abs(delta.x) > 1 and delta.y == 0:
            tail.x += delta.x - delta.polarity_x
        if abs(delta.x) > 1 and abs(delta.y) == 1:
            tail.x += delta.x - delta.polarity_x
            tail.y += delta.y
        if abs(delta.y > 1) and delta.x == 0:
            tail.y += delta.y - delta.polarity_y
        if abs(delta.y) > 1 and abs(delta.x) == 1:
            tail.y += delta.y - delta.polarity_y
            tail.x += delta.x

    def tail_positions(self, input: Iterator[str]) -> Iterator[Coordinate]:
        head = Coordinate(0, 0)
        tail = Coordinate(0, 0)

        for line in input:
            direction, amount = self.parse_line(line)

            for _ in range(amount):
                self.next_head(head, direction)
                self.next_tail(head, tail)
                yield tail


class AssignmentOne(Assignment):
    example_result = 13

    def run(self, input: Iterator) -> int:
        unique_tail_positions = set()

        for position in self.tail_positions(input):
            unique_tail_positions.add(copy(position))

        print(unique_tail_positions)

        for y in range(5):
            items = []
            for x in range(6):
                if Coordinate(x, y) in unique_tail_positions:
                    items.append("#")
                else:
                    items.append(".")
            print("".join(items))

        return len(unique_tail_positions)


class AssignmentTwo(Assignment):
    pass