2022-09 py
Signed-off-by: AKP <tom@tdpain.net>
This commit is contained in:
parent
d336034cbd
commit
9c3e041e7e
6 changed files with 143 additions and 0 deletions
1
challenges/2022/09-ropeBridge/README.md
Normal file
1
challenges/2022/09-ropeBridge/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# [Day 9: Rope Bridge](https://adventofcode.com/2022/day/9)
|
15
challenges/2022/09-ropeBridge/benchmark.json
Normal file
15
challenges/2022/09-ropeBridge/benchmark.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"day": 9,
|
||||
"dir": "challenges/2022/09-ropeBridge",
|
||||
"implementations": {
|
||||
"Python": {
|
||||
"part.1.avg": 0.40573710823059084,
|
||||
"part.1.max": 0.5149297714233398,
|
||||
"part.1.min": 0.3336000442504883,
|
||||
"part.2.avg": 0.08495945644378662,
|
||||
"part.2.max": 0.13427042961120605,
|
||||
"part.2.min": 0.0677499771118164
|
||||
}
|
||||
},
|
||||
"numRuns": 250
|
||||
}
|
21
challenges/2022/09-ropeBridge/info.json
Normal file
21
challenges/2022/09-ropeBridge/info.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"inputFile": "input.txt",
|
||||
"testCases": {
|
||||
"one": [
|
||||
{
|
||||
"input": "R 4\nU 4\nL 3\nD 1\nR 4\nD 1\nL 5\nR 2",
|
||||
"expected": "13"
|
||||
}
|
||||
],
|
||||
"two": [
|
||||
{
|
||||
"input": "R 4\nU 4\nL 3\nD 1\nR 4\nD 1\nL 5\nR 2",
|
||||
"expected": "1"
|
||||
},
|
||||
{
|
||||
"input": "R 5\nU 8\nL 8\nD 3\nR 17\nD 10\nL 25\nU 20\n",
|
||||
"expected": "36"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
105
challenges/2022/09-ropeBridge/py/__init__.py
Normal file
105
challenges/2022/09-ropeBridge/py/__init__.py
Normal file
|
@ -0,0 +1,105 @@
|
|||
from typing import *
|
||||
from aocpy import BaseChallenge
|
||||
|
||||
Vector = Tuple[int, int]
|
||||
Instruction = Tuple[str, int]
|
||||
|
||||
LEFT = "L"
|
||||
RIGHT = "R"
|
||||
UP = "U"
|
||||
DOWN = "D"
|
||||
|
||||
OFFSETS = {
|
||||
RIGHT: (1, 0),
|
||||
LEFT: (-1, 0),
|
||||
UP: (0, 1),
|
||||
DOWN: (0, -1),
|
||||
}
|
||||
|
||||
|
||||
def parse(instr: str) -> List[Instruction]:
|
||||
return [(x[0], int(x[2:])) for x in instr.strip().splitlines()]
|
||||
|
||||
|
||||
def apply_delta(coord: Vector, delta: Vector) -> Vector:
|
||||
return (coord[0] + delta[0], coord[1] + delta[1])
|
||||
|
||||
|
||||
def vector_sum(a: Vector, b: Vector) -> Vector:
|
||||
return (a[0] + b[0], a[1] + b[1])
|
||||
|
||||
|
||||
def vector_diff(a: Vector, b: Vector) -> Vector:
|
||||
return (a[0] - b[0], a[1] - b[1])
|
||||
|
||||
|
||||
def get_next_move_delta(
|
||||
current_position: Vector, preceeding_position: Vector
|
||||
) -> Optional[Vector]:
|
||||
(dx, dy) = vector_diff(preceeding_position, current_position)
|
||||
|
||||
if -1 <= dx <= 1 and -1 <= dy <= 1:
|
||||
return None
|
||||
|
||||
if dy > 0 and dx == 0:
|
||||
# head upwards of tail
|
||||
return OFFSETS[UP]
|
||||
elif dy < 0 and dx == 0:
|
||||
# head downwards of tail
|
||||
return OFFSETS[DOWN]
|
||||
elif dy == 0 and dx > 0:
|
||||
# head to the right of tail
|
||||
return OFFSETS[RIGHT]
|
||||
elif dy == 0 and dx < 0:
|
||||
# head to the left of tail
|
||||
return OFFSETS[LEFT]
|
||||
elif dy > 0 and dx > 0:
|
||||
# head diagonally up-right of the tail
|
||||
return vector_sum(OFFSETS[UP], OFFSETS[RIGHT])
|
||||
elif dy > 0 and dx < 0:
|
||||
# head diagonally up-left of the tail
|
||||
return vector_sum(OFFSETS[UP], OFFSETS[LEFT])
|
||||
elif dy < 0 and dx > 0:
|
||||
# head diagonally down-right of the tail
|
||||
return vector_sum(OFFSETS[DOWN], OFFSETS[RIGHT])
|
||||
elif dy < 0 and dx < 0:
|
||||
# head diagonally down-left of the tail
|
||||
return vector_sum(OFFSETS[DOWN], OFFSETS[LEFT])
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def run_with_length(instructions: List[Instruction], length: int) -> int:
|
||||
tail_visited: List[Vector] = [(0, 0)]
|
||||
|
||||
positions: List[Vector] = [(0, 0) for _ in range(length)]
|
||||
|
||||
for (direction, magnitude) in instructions:
|
||||
for _ in range(magnitude):
|
||||
positions[0] = apply_delta(positions[0], OFFSETS[direction])
|
||||
|
||||
for pos_num in range(1, len(positions)):
|
||||
delta = get_next_move_delta(positions[pos_num], positions[pos_num - 1])
|
||||
if delta is None:
|
||||
break
|
||||
|
||||
positions[pos_num] = apply_delta(positions[pos_num], delta)
|
||||
|
||||
if delta is None:
|
||||
# Python scope nastiness coming in useful for once
|
||||
continue
|
||||
|
||||
if positions[-1] not in tail_visited:
|
||||
tail_visited.append(positions[-1])
|
||||
|
||||
return len(tail_visited)
|
||||
|
||||
|
||||
class Challenge(BaseChallenge):
|
||||
@staticmethod
|
||||
def one(instr: str) -> int:
|
||||
return run_with_length(parse(instr), 2)
|
||||
|
||||
@staticmethod
|
||||
def two(instr: str) -> int:
|
||||
return run_with_length(parse(instr), 10)
|
|
@ -22,4 +22,5 @@ Solutions to the [2022 Advent of Code](https://adventofcode.com/2022).
|
|||
| 06 - Tuning Trouble | ★ ★ | [Python](06-tuningTrouble/py), [Nim](06-tuningTrouble/nim) | This is the first year I've not repeatedly forgotten about the existence of sets, and it's coming in quite handy. |
|
||||
| 07 - No Space Left On Device | ★ ★ | [Python](07-noSpaceLeftOnDevice/py) | Turns out that fake file systems are prone to very subtle and infuriating bugs. |
|
||||
| 08 - Treetop Tree House | ★ ★ | [Python](08-treetopTreeHouse/py) | Magical coordinate dictionary tuple things do be magical. |
|
||||
| 09 - Rope Bridge | ★ ★ | [Python](09-ropeBridge/py) | Does this count as this year's first cellular automata? |
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 59 KiB |
Loading…
Add table
Add a link
Reference in a new issue