109 lines
3.4 KiB
Python
Executable File
109 lines
3.4 KiB
Python
Executable File
#!/usr/bin/python3
|
|
"""
|
|
Jour 16 du défi Advent Of Code pour l'année 2023
|
|
"""
|
|
import os
|
|
from functools import cache, wraps
|
|
from tqdm import tqdm
|
|
import time
|
|
|
|
def read_sample() -> list[str]:
|
|
"""récupère les entrées depuis le fichier texte correspondant"""
|
|
filename = os.path.join(os.path.dirname(__file__ ), "inputs", "day16.txt")
|
|
with open(filename, 'r') as f:
|
|
sample = f.read().split('\n')
|
|
sample = [ i for i in sample if i != '' ]
|
|
return sample
|
|
|
|
|
|
def timeit(func):
|
|
@wraps(func)
|
|
def timeit_wrapper(*args, **kwargs):
|
|
start_time = time.perf_counter()
|
|
result = func(*args, **kwargs)
|
|
end_time = time.perf_counter()
|
|
total_time = end_time - start_time
|
|
print(f'Function {func.__name__} Took {total_time:.4f} seconds')
|
|
return result
|
|
return timeit_wrapper
|
|
|
|
|
|
def diff(l1: set, l2: set) -> bool:
|
|
return len(l1 ^ l2) > 0
|
|
|
|
def energize(sample: list[str], initial: tuple[tuple[int, int], tuple[int, int]]=((0, 0), (0, 1))) -> set[tuple[tuple[int, int], tuple[int, int]]]:
|
|
def step(position: tuple[int, int], direction: tuple[int, int]):
|
|
match sample[position[0]][position[1]]:
|
|
case '\\':
|
|
return [(direction[1], direction[0])]
|
|
case '/':
|
|
return [(-direction[1], -direction[0])]
|
|
case '.':
|
|
return [direction]
|
|
case '-':
|
|
if direction[0] != 0:
|
|
return [(0, 1), (0, -1)]
|
|
return [direction]
|
|
case '|':
|
|
if direction[1] != 0:
|
|
return [(1, 0), (-1, 0)]
|
|
return [direction]
|
|
|
|
directions = set([initial]) # List[positions, directions]
|
|
modif = True
|
|
while modif:
|
|
new_directions = set([initial])
|
|
for pos, direction in directions:
|
|
new = step(pos, direction)
|
|
for dir_t in new:
|
|
pos_t = (pos[0]+dir_t[0], pos[1]+dir_t[1])
|
|
if pos_t[0] >= 0 and pos_t[1] >= 0 and pos_t[0] < len(sample) and pos_t[1] < len(sample[0]):
|
|
new_directions.add(( pos_t, dir_t ))
|
|
|
|
modif = diff(directions, new_directions)
|
|
directions = new_directions
|
|
#print(new_directions)
|
|
|
|
return directions
|
|
|
|
|
|
@timeit
|
|
def part1(sample: list[str]) -> int:
|
|
"""Partie 1 du défi"""
|
|
dir_pos = energize(sample)
|
|
energized = {i[0] for i in dir_pos}
|
|
return len(energized)
|
|
|
|
@timeit
|
|
def part2(sample: list[str]) -> int:
|
|
"""Partie 2 du défi"""
|
|
best = 0
|
|
for i in tqdm(range(len(sample))):
|
|
dir_pos = energize(sample, initial=((i, 0), (0, 1)))
|
|
energized = {i[0] for i in dir_pos}
|
|
best = max(len(energized), best)
|
|
|
|
dir_pos = energize(sample, initial=((i, len(sample)-1), (0, -1)))
|
|
energized = {i[0] for i in dir_pos}
|
|
best = max(len(energized), best)
|
|
|
|
for j in tqdm(range(len(sample[0]))):
|
|
dir_pos = energize(sample, initial=((0, j), (1, 0)))
|
|
energized = {i[0] for i in dir_pos}
|
|
best = max(len(energized), best)
|
|
|
|
dir_pos = energize(sample, initial=(((len(sample[0])-1, j)), (-1, 0)))
|
|
energized = {i[0] for i in dir_pos}
|
|
best = max(len(energized), best)
|
|
|
|
return best
|
|
|
|
|
|
def main() -> None:
|
|
"""Fonction principale"""
|
|
sample = read_sample()
|
|
print(f"part1: {part1(sample)}")
|
|
print(f"part2: {part2(sample)}")
|
|
|
|
if __name__ == "__main__":
|
|
main() |