This commit is contained in:
cupcakearmy 2022-12-10 02:11:53 +01:00
parent 34bead126f
commit 16dbc2cd1a
2 changed files with 123 additions and 0 deletions

11
2022/09/README.md Normal file
View File

@ -0,0 +1,11 @@
# 09
This took me waaay longer than it should be. The first part was quick and easy, but in the second part my diagonal logic was flawed. Then the "this is to late I should go to sleep" mode kicked in.
<details>
<summary>Solutions</summary>
<ol>
<li>5695</li>
<li>2434</li>
</ol>
</details>

112
2022/09/python/main.py Normal file
View File

@ -0,0 +1,112 @@
#!/usr/bin/env python
from dataclasses import dataclass
from os.path import dirname, join
from typing import Literal
# Day 09
# 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)
def __sub__(self, other: 'Point'):
return Point(self.x - other.x, self.y - other.y)
def distance(self, other: 'Point') -> int:
return max(abs(self.x - other.x), abs(self.y-other.y))
def normalise(self):
self.x = max(-1, min(1, self.x))
self.y = max(-1, min(1, self.y))
return self
Directions = Literal['U', 'D', 'L', 'R']
Instruction = tuple[Directions, int]
MAPPING: dict[Directions, Point] = {'U': Point(0, 1), 'D': Point(0, -1), 'L': Point(-1, 0), 'R': Point(1, 0)}
class Rope:
def __init__(self, instructions: list[Instruction], links: int) -> None:
self.instructions = instructions
start = Point(0, 0)
self.touched: set[Point] = set([start])
self.links = [start for _ in range(links)]
def move(self, instruction: Instruction):
direction, travel = instruction
last = len(self.links) - 1
for _ in range(travel):
moved: list[Point] = []
for i, link in enumerate(self.links):
if i == 0:
link = link + MAPPING[direction]
else:
head = moved[i-1]
distance = head.distance(link)
if distance > 1:
link = link + (head - link).normalise()
moved.append(link)
if i == last:
self.touched.add(link)
self.links = moved
def run(self):
for instruction in self.instructions:
self.move(instruction)
return len(self.touched)
@staticmethod
def visualise(points: list[Point], numbered=True) -> str:
"""
Only used to visualise, not actual logic
"""
max_x = max(p.x for p in points)
min_x = min(p.x for p in points)
max_y = max(p.y for p in points)
min_y = min(p.y for p in points)
range_x = max_x - min_x
range_y = max_y - min_y
grid = [
['.' for _ in range(range_x+1)]
for _ in range(range_y+1)
]
for i, link in enumerate(points):
row = grid[range_y-(link.y - min_y)]
if row[link.x-min_x] == '.':
row[link.x-min_x] = str(i) if numbered else "#"
return '\n'.join(map(lambda line: ''.join(line), grid))
@staticmethod
def parse(data: str, links: int):
instructions = [
(i[0], int(i[1]))
for i in map(lambda line: line.split(), data.splitlines())
]
return Rope(instructions, links)
# Running
grid = Rope.parse(data, 2)
print(grid.run())
grid = Rope.parse(data, 10)
print(grid.run())