Skip to content

Commit

Permalink
add 15, 16, 17
Browse files Browse the repository at this point in the history
  • Loading branch information
JasperZP committed Dec 18, 2023
1 parent 851d93d commit fe04b4a
Show file tree
Hide file tree
Showing 3 changed files with 417 additions and 0 deletions.
90 changes: 90 additions & 0 deletions 15/15.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import typer
import re
import functools
from rich.logging import RichHandler
import logging
from rich.progress import track, Progress

from multiprocessing import Pool, freeze_support

FORMAT = "%(message)s"
logging.basicConfig(
level="DEBUG", format=FORMAT, datefmt="[%X]", handlers=[RichHandler()]
)
log = logging.getLogger("rich")


def clac_hash(string: str) -> int:
current_value = 0
for c in string:
current_value += ord(c)
current_value *= 17
current_value %= 256
log.debug(f"{string} -> {current_value}")
return current_value


def calc_focussing_power(boxes: list) -> int:
fp_sum = 0
for i, box in enumerate(boxes):
if not box:
continue
for j, (lens, focal_length) in enumerate(box.items()):
fp = 1 + i
fp *= j + 1
fp *= focal_length
fp_sum += fp
return fp_sum


def print_boxes(boxes: list):
for i, box in enumerate(boxes):
if not box:
continue
log.debug(f"Box {i}:")
for j, (lens, focal_length) in enumerate(box.items()):
log.debug(f" slot {j}: {lens} {focal_length}")


def main(
input_file: typer.FileText,
log_level: str = "INFO",
part1: bool = True,
part2: bool = True,
):
log.setLevel(log_level)
line = input_file.read().strip().replace("\n", "").replace("\r", "")

if part1:
current_value = 0
for step in track(line.split(",")):
current_value += clac_hash(step)
log.info(f"Part1: {current_value}")

if part2:
boxes = [None] * 256
for step in track(line.split(",")):
if "-" in step:
lens = step.split("-")[0]
box = clac_hash(lens)
if boxes[box] and lens in boxes[box]:
boxes[box].pop(lens)
log.debug(f"Step: {step} -> Box {box}: {boxes[box]}")
elif "=" in step:
lens = step.split("=")[0]
strength = int(step.split("=")[1])
box = clac_hash(lens)
if not boxes[box]:
boxes[box] = {}
boxes[box][lens] = strength
log.debug(f"Step: {step} -> Box {box}: {boxes[box]}")
else:
raise ValueError(f"Unknown step: {step}")
print_boxes(boxes)
fp = calc_focussing_power(boxes)
log.info(f"Part2: {fp}")


if __name__ == "__main__":
freeze_support()
typer.run(main)
184 changes: 184 additions & 0 deletions 16/16.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import typer
import re
import functools
from rich.logging import RichHandler
import logging
from rich.progress import track, Progress
import math
from enum import Enum

from multiprocessing import Pool, freeze_support

FORMAT = "%(message)s"
logging.basicConfig(
level="DEBUG", format=FORMAT, datefmt="[%X]", handlers=[RichHandler()]
)
log = logging.getLogger("rich")


class Heading(Enum):
NORTH = 0
EAST = 1
SOUTH = 2
WEST = 3


def new_pos(pos: tuple[int], heading: Heading) -> tuple[int]:
if heading == Heading.NORTH:
return (pos[0] - 1, pos[1])
elif heading == Heading.EAST:
return (pos[0], pos[1] + 1)
elif heading == Heading.SOUTH:
return (pos[0] + 1, pos[1])
elif heading == Heading.WEST:
return (pos[0], pos[1] - 1)


def print_energized(layout: list[str], positions: set[tuple]):
for i, row in enumerate(layout):
for j, col in enumerate(row):
if (i, j) in positions:
print("#", end="")
else:
print(".", end="")
print()


def num_tiles_traversed(
layout: list[str],
pos: tuple[int] = (0, -1),
heading: Heading = Heading.EAST,
positions_traversed: set[tuple] | None = None,
) -> set[tuple[int]]:
width = len(layout[0])
height = len(layout)

if positions_traversed is None:
positions_traversed = set()

while True:
pos = new_pos(pos, heading)
if pos[0] < 0 or pos[0] >= height or pos[1] < 0 or pos[1] >= width:
log.debug(
f"Out of bounds, positions traversed: {len(positions_traversed)}"
)
break
if (pos, heading) in positions_traversed:
log.debug(
f"Loop detected, positions traversed: {len(positions_traversed)}"
)
break
log.debug(f"New pos: {pos} ({heading} {layout[pos[0]][pos[1]]})")
positions_traversed.add((pos, heading))
if heading == Heading.NORTH:
if layout[pos[0]][pos[1]] == "-":
positions_traversed.update(
num_tiles_traversed(
layout, pos, Heading.WEST, positions_traversed
)
)
heading = Heading.EAST
elif layout[pos[0]][pos[1]] == "/":
heading = Heading.EAST
elif layout[pos[0]][pos[1]] == "\\":
heading = Heading.WEST
elif heading == Heading.EAST:
if layout[pos[0]][pos[1]] == "|":
positions_traversed.update(
num_tiles_traversed(
layout, pos, Heading.NORTH, positions_traversed
)
)
heading = Heading.SOUTH
elif layout[pos[0]][pos[1]] == "/":
heading = Heading.NORTH
elif layout[pos[0]][pos[1]] == "\\":
heading = Heading.SOUTH
elif heading == Heading.SOUTH:
if layout[pos[0]][pos[1]] == "-":
positions_traversed.update(
num_tiles_traversed(
layout, pos, Heading.WEST, positions_traversed
)
)
heading = Heading.EAST
elif layout[pos[0]][pos[1]] == "/":
heading = Heading.WEST
elif layout[pos[0]][pos[1]] == "\\":
heading = Heading.EAST
elif heading == Heading.WEST:
if layout[pos[0]][pos[1]] == "|":
positions_traversed.update(
num_tiles_traversed(
layout, pos, Heading.NORTH, positions_traversed
)
)
heading = Heading.SOUTH
elif layout[pos[0]][pos[1]] == "/":
heading = Heading.SOUTH
elif layout[pos[0]][pos[1]] == "\\":
heading = Heading.NORTH

return positions_traversed


def main(
input_file: typer.FileText,
log_level: str = "INFO",
part1: bool = True,
part2: bool = True,
):
log.setLevel(log_level)
layout = input_file.read().strip().split("\n")

if part1:
positions_traversed = num_tiles_traversed(layout)
positions_traversed = {pos for pos, heading in positions_traversed}
print_energized(layout, positions_traversed)
num_tiles = len(positions_traversed)
log.info(f"Part 1: {num_tiles}")

if part2:
positions_traversed = set()
width = len(layout[0])
height = len(layout)
pt_max = 0
for y in track(
range(height),
description="Traversing with light from top to bottom",
):
positions_traversed = num_tiles_traversed(
layout, (y, -1), Heading.EAST
)
pt_max = max(
pt_max, len(set({pos for pos, heading in positions_traversed}))
)
positions_traversed = num_tiles_traversed(
layout, (y, width), Heading.WEST
)
pt_max = max(
pt_max, len(set({pos for pos, heading in positions_traversed}))
)
for x in track(
range(width),
description="Traversing with light from left to right",
):
positions_traversed = num_tiles_traversed(
layout, (-1, x), Heading.SOUTH
)
pt_max = max(
pt_max, len(set({pos for pos, heading in positions_traversed}))
)
positions_traversed = num_tiles_traversed(
layout, (height, x), Heading.NORTH
)
pt_max = max(
pt_max, len(set({pos for pos, heading in positions_traversed}))
)
# num_tiles = len(positions_traversed)
log.info(f"Part 2: {pt_max}")


if __name__ == "__main__":
freeze_support()
typer.run(main)
Loading

0 comments on commit fe04b4a

Please sign in to comment.