summaryrefslogtreecommitdiffstats
path: root/day14/__init__.py
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <t0m.vd.l33@gmail.com>2022-12-15 22:14:01 +0100
committerGravatar Tom van der Lee <t0m.vd.l33@gmail.com>2022-12-15 22:14:01 +0100
commit9d716dcf2b49abc34a7f52d2cbe879b7aba13421 (patch)
treedcab7e6fe2efca7b187aaaad7660c37b662b5c6e /day14/__init__.py
parent3046c118d13757219a274b904368df41156474e2 (diff)
download2022-9d716dcf2b49abc34a7f52d2cbe879b7aba13421.tar.gz
2022-9d716dcf2b49abc34a7f52d2cbe879b7aba13421.tar.bz2
2022-9d716dcf2b49abc34a7f52d2cbe879b7aba13421.zip
Day 14
Diffstat (limited to 'day14/__init__.py')
-rw-r--r--day14/__init__.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/day14/__init__.py b/day14/__init__.py
new file mode 100644
index 0000000..44107de
--- /dev/null
+++ b/day14/__init__.py
@@ -0,0 +1,133 @@
1# -*- coding: utf-8 -*-
2from abc import ABC
3from functools import lru_cache
4from typing import Tuple, Iterator, Set, Any, Optional
5
6from aoc import BaseAssignment
7
8Coordinate = Tuple[int, int]
9
10
11class Assignment(BaseAssignment, ABC):
12 def __init__(self, path):
13 super().__init__(path)
14
15 self.cave_depth = None
16
17 def coordinate_ranges(
18 self, input: Iterator[str]
19 ) -> Iterator[Tuple[Coordinate, Coordinate]]:
20 for item in input:
21 last = None
22
23 for i in item.split(" -> "):
24 x, y = i.split(",")
25
26 coordinate = int(x), int(y)
27
28 if last is not None:
29 yield last, coordinate
30
31 last = coordinate
32
33 def coordinates(self, a: Coordinate, b: Coordinate) -> Iterator[Coordinate]:
34 for x in range(min(a[0], b[0]), max(a[0], b[0]) + 1):
35 for y in range(min(a[1], b[1]), max(a[1], b[1]) + 1):
36 yield x, y
37
38 def generate_rocks(self, input: Iterator[str]) -> Set[Coordinate]:
39 rocks = set(
40 coordinate
41 for coordinates in self.coordinate_ranges(input)
42 for coordinate in self.coordinates(*coordinates)
43 )
44
45 self.cave_depth = self.get_cave_depth(rocks)
46
47 return rocks
48
49 def get_cave_depth(self, cave: Set[Coordinate]):
50 return max([item[1] for item in cave])
51
52 def invalid_position(self, sand: Coordinate, cave: set[Coordinate]):
53 raise NotImplementedError()
54
55 def blocking(self, sand: Coordinate, cave: set[Coordinate]):
56 raise NotImplementedError()
57
58 def drop_sand(
59 self, sand: Coordinate, cave: Set[Coordinate]
60 ) -> Optional[Coordinate]:
61 if self.invalid_position(sand, cave):
62 return None
63
64 next_positions = [
65 (sand[0], sand[1] + 1),
66 (sand[0] - 1, sand[1] + 1),
67 (sand[0] + 1, sand[1] + 1),
68 ]
69
70 non_blocking = [
71 next_position
72 for next_position in next_positions
73 if not self.blocking(next_position, cave)
74 ]
75
76 if len(non_blocking) == 0:
77 return sand
78
79 return self.drop_sand(non_blocking[0], cave)
80
81 def generate_sand(self, cave: set[Coordinate]) -> Iterator[Coordinate]:
82 cave_copy = set(cave)
83 sand = (500, 0)
84
85 while True:
86 coordinate = self.drop_sand(sand, cave_copy)
87
88 if coordinate is None:
89 return
90
91 cave_copy.add(coordinate)
92 yield coordinate
93
94 def run(self, input: Iterator) -> Any:
95 cave = self.generate_rocks(input)
96 coordinates = set()
97
98 for sand in self.generate_sand(cave):
99 coordinates.add(sand)
100
101 return len(coordinates)
102
103
104class AssignmentOne(Assignment):
105 example_result = 24
106
107 def invalid_position(self, sand: Coordinate, cave: set[Coordinate]):
108 return sand[1] > self.cave_depth
109
110 def blocking(self, sand: Coordinate, cave: set[Coordinate]):
111 return sand in cave
112
113
114class AssignmentTwo(Assignment):
115 example_result = 93
116
117 def invalid_position(self, sand: Coordinate, cave: set[Coordinate]):
118 return False
119
120 def blocking(self, sand: Coordinate, cave: set[Coordinate]):
121 return sand in cave or sand[1] >= self.cave_depth + 2
122
123 def run(self, input: Iterator) -> Any:
124 cave = self.generate_rocks(input)
125 coordinates = set()
126
127 for sand in self.generate_sand(cave):
128 coordinates.add(sand)
129
130 if sand == (500, 0):
131 break
132
133 return len(coordinates)