mirror of
https://github.com/cupcakearmy/advent-of-code.git
synced 2024-12-21 23:56:30 +00:00
14
This commit is contained in:
parent
57aa1dc083
commit
f4fb4fb64f
11
2022/14/README.md
Normal file
11
2022/14/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 14
|
||||||
|
|
||||||
|
Mucho loops this time. Logic wise quite straight forward.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Solutions</summary>
|
||||||
|
<ol>
|
||||||
|
<li>698</li>
|
||||||
|
<li>28594</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
105
2022/14/python/main.py
Normal file
105
2022/14/python/main.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from os.path import dirname, join
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
# Day 14
|
||||||
|
|
||||||
|
# Common
|
||||||
|
|
||||||
|
|
||||||
|
def read_input(filename):
|
||||||
|
data = join(dirname(__file__), '..', filename)
|
||||||
|
with open(data) as f:
|
||||||
|
return f.read().strip()
|
||||||
|
|
||||||
|
|
||||||
|
test = read_input('test.txt')
|
||||||
|
data = read_input('input.txt')
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(unsafe_hash=True)
|
||||||
|
class Point:
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
|
||||||
|
def __add__(self, other: 'Point'):
|
||||||
|
return Point(self.x+other.x, self.y+other.y)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Cave:
|
||||||
|
sand: set[Point]
|
||||||
|
rocks: set[Point]
|
||||||
|
boundaries: dict[Literal['max_y', 'max_x', 'min_x', 'min_y'], int]
|
||||||
|
bottom: bool = False
|
||||||
|
source: Point = Point(500, 0)
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
s = ''
|
||||||
|
for y in range(self.boundaries['min_y'], self.boundaries['max_y']+1):
|
||||||
|
s += '\n'
|
||||||
|
for x in range(self.boundaries['min_x'], self.boundaries['max_x']+1):
|
||||||
|
p = Point(x, y)
|
||||||
|
if p == self.source:
|
||||||
|
s += '+'
|
||||||
|
elif p in self.sand:
|
||||||
|
s += 'O'
|
||||||
|
elif p in self.rocks:
|
||||||
|
s += '#'
|
||||||
|
else:
|
||||||
|
s += '.'
|
||||||
|
print(s)
|
||||||
|
|
||||||
|
def produce(self) -> bool:
|
||||||
|
movements = [Point(0, 1), Point(-1, 1), Point(1, 1)]
|
||||||
|
sanddorn = self.source
|
||||||
|
while True:
|
||||||
|
moved = False
|
||||||
|
for movement in movements:
|
||||||
|
p = sanddorn + movement
|
||||||
|
if p in self.sand or p in self.rocks:
|
||||||
|
continue
|
||||||
|
if self.bottom and p.y == self.boundaries['max_y']+2:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if not self.bottom and p.y >= self.boundaries['max_y']:
|
||||||
|
return False
|
||||||
|
sanddorn = p
|
||||||
|
moved = True
|
||||||
|
break
|
||||||
|
if not moved:
|
||||||
|
self.sand.add(sanddorn)
|
||||||
|
return self.source != sanddorn
|
||||||
|
|
||||||
|
def simulate(self):
|
||||||
|
while self.produce():
|
||||||
|
pass
|
||||||
|
return len(self.sand)
|
||||||
|
|
||||||
|
@ staticmethod
|
||||||
|
def parse(data: str, bottom=False) -> 'Cave':
|
||||||
|
rocks = [[[
|
||||||
|
int(coordinate)
|
||||||
|
for coordinate in segment.split(',')]
|
||||||
|
for segment in rock.split(' -> ')]
|
||||||
|
for rock in data.splitlines()]
|
||||||
|
points: set[Point] = set()
|
||||||
|
xs: list[int] = []
|
||||||
|
ys: list[int] = []
|
||||||
|
for rock in rocks:
|
||||||
|
for i in range(len(rock)-1):
|
||||||
|
a, b = rock[i], rock[i+1]
|
||||||
|
x_min, y_min = min(a[0], b[0]), min(a[1], b[1])
|
||||||
|
for dx in range(x_min, x_min + abs(a[0]-b[0])+1):
|
||||||
|
for dy in range(y_min, y_min + abs(a[1]-b[1])+1):
|
||||||
|
xs.append(dx)
|
||||||
|
ys.append(dy)
|
||||||
|
points.add(Point(dx, dy))
|
||||||
|
return Cave(set(), points, {'min_y': 0, 'max_y': max(ys), 'min_x': min(xs), 'max_x': max(xs)}, bottom)
|
||||||
|
|
||||||
|
|
||||||
|
# Running
|
||||||
|
cave = Cave.parse(data, bottom=True)
|
||||||
|
print(cave.simulate())
|
Loading…
Reference in New Issue
Block a user