"""Day15 solution."""
from day15.lib.classes import AddRemove, Box, Lens, Step
INPUT = "day15/input.txt"
INPUT_SMALL = "day15/input-small.txt"
[docs]
def get_string_hash(string: str) -> int:
"""Returns a string's ``hash``."""
value: int = 0
for char in string:
value += ord(char)
value *= 17
value %= 256
return value
[docs]
def parse_step_pt2(raw_step: str) -> Step:
"""Handles as step in part 2."""
if len(splits := raw_step.split("=")) == 2:
box = get_string_hash(splits[0])
strength = int(splits[1].strip())
return Step(splits[0], box, AddRemove.Add, strength)
elif len(splits := raw_step.split("-")) == 2:
box = get_string_hash(splits[0])
return Step(splits[0], box, AddRemove.Remove)
raise AssertionError("Raw step does not contain `-` or `=`")
[docs]
def process_steps_pt2(steps: list[Step]) -> int:
"""Process a list of steps."""
boxes: list[Box] = [Box(i) for i in range(256)]
for step in steps:
if step.process == AddRemove.Remove:
boxes[step.box].remove_lens(step.lens_name)
else:
if step.focal_length is None:
raise AssertionError("focal length should not be None")
lens = Lens(step.lens_name, step.focal_length)
boxes[step.box].add_lens(lens)
return sum(box.calculate_power() for box in boxes)
[docs]
def question1(raw_steps: list[str]) -> int:
"""Returns the sum of hashes for every step."""
return sum(get_string_hash(raw_step) for raw_step in raw_steps)
[docs]
def question2(raw_steps: list[str]) -> int:
"""Process each step into "lens" boxes and return the total lens power."""
steps = [parse_step_pt2(raw_step) for raw_step in raw_steps]
return process_steps_pt2(steps)
[docs]
def main() -> None:
"""Read input and call question1/question2."""
raw_steps = get_input(INPUT)
# q1
print(question1(raw_steps))
# q2
print(question2(raw_steps))
if __name__ == "__main__":
main()