2023: d15: ex2: add solution
This commit is contained in:
parent
e253096a7e
commit
d35af3ede7
76
2023/d15/ex2/ex2.py
Executable file
76
2023/d15/ex2/ex2.py
Executable file
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import dataclasses
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Lens:
|
||||
label: str
|
||||
num: int
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if isinstance(other, str):
|
||||
return self.label == other
|
||||
return super().__eq__(other)
|
||||
|
||||
|
||||
def solve(input: list[str]) -> int:
|
||||
def compute_hash(string: str) -> int:
|
||||
res = 0
|
||||
|
||||
for c in string:
|
||||
res += ord(c)
|
||||
res *= 17
|
||||
res %= 256
|
||||
|
||||
return res
|
||||
|
||||
def parse_step(step: str) -> tuple[str, Optional[int]]:
|
||||
if step[-1] == "-":
|
||||
return step[:-1], None
|
||||
label, num = step.split("=")
|
||||
return label, int(num)
|
||||
|
||||
def find_label(label: str, box: list[Lens]) -> Optional[int]:
|
||||
for i, lens in enumerate(box):
|
||||
if lens.label == label:
|
||||
return i
|
||||
return None
|
||||
|
||||
def focusing_power(boxes: list[list[Lens]]) -> int:
|
||||
res = 0
|
||||
|
||||
for box_num, box in enumerate(boxes, start=1):
|
||||
for i, lens in enumerate(box, start=1):
|
||||
res += box_num * i * lens.num
|
||||
|
||||
return res
|
||||
|
||||
boxes: list[list[Lens]] = [[] for _ in range(256)]
|
||||
|
||||
for label, num in map(parse_step, input):
|
||||
box = compute_hash(label)
|
||||
index = find_label(label, boxes[box])
|
||||
if num is None:
|
||||
# Remove label from box
|
||||
if index is not None:
|
||||
del boxes[box][index]
|
||||
# Place len in box
|
||||
elif index is not None:
|
||||
boxes[box][index].num = num
|
||||
else:
|
||||
boxes[box].append(Lens(label, num))
|
||||
|
||||
return focusing_power(boxes)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
input = sys.stdin.read().splitlines()
|
||||
assert len(input) == 1 # Sanity check
|
||||
print(solve(input[0].split(",")))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in a new issue