55 lines
1.3 KiB
Python
55 lines
1.3 KiB
Python
import sys
|
|
from typing import Literal, TypeAlias, cast
|
|
|
|
Direction: TypeAlias = Literal["R", "L", "U", "D"]
|
|
|
|
DIRECTIONS: list[Direction] = ["R", "D", "L", "U"]
|
|
MOVES: dict[Direction, tuple[int, int]] = {
|
|
"R": (0, +1),
|
|
"L": (0, -1),
|
|
"U": (-1, 0),
|
|
"D": (+1, 0),
|
|
}
|
|
|
|
|
|
def area(corners: list[tuple[int, int]], perimeter: int) -> int:
|
|
area = abs(
|
|
sum(c0[0] * c1[1] - c0[1] * c1[0] for c0, c1 in zip(corners, corners[1::])) // 2
|
|
)
|
|
return 1 + area - perimeter // 2 + perimeter
|
|
|
|
|
|
def polygon(values: list[tuple[Direction, int]]) -> tuple[list[tuple[int, int]], int]:
|
|
perimeter = 0
|
|
corners: list[tuple[int, int]] = [(0, 0)]
|
|
for direction, amount in values:
|
|
perimeter += amount
|
|
corners.append(
|
|
(
|
|
corners[-1][0] + amount * MOVES[direction][0],
|
|
corners[-1][1] + amount * MOVES[direction][1],
|
|
)
|
|
)
|
|
return corners, perimeter
|
|
|
|
|
|
lines = sys.stdin.read().splitlines()
|
|
|
|
|
|
# part 1
|
|
answer_1 = area(
|
|
*polygon([(cast(Direction, (p := line.split())[0]), int(p[1])) for line in lines])
|
|
)
|
|
print(f"answer 1 is {answer_1}")
|
|
|
|
# part 2
|
|
answer_2 = area(
|
|
*polygon(
|
|
[
|
|
(DIRECTIONS[int((h := line.split()[-1])[-2])], int(h[2:-2], 16))
|
|
for line in lines
|
|
]
|
|
)
|
|
)
|
|
print(f"answer 2 is {answer_2}")
|