◂ 14 décembre 2023 ▸
Parabolic Reflector Dish : Faire glisser des cailloux dans 4 directions successives
...O.....#O#... …
#OO..O.##..#... …
.###..O.#...O.# …
O.O......OO.O#. …
.#....#.O#...O. …
.#.....O..#...# …
⋮
- code.py
- code_optim_deplacer_cailloux.py
- code_oneLiners_lievreTortue.py
- code_numpy.py
from typing import MutableSequence
f = open("input.txt", 'r', encoding='utf-8')
lines = [line[:-1] for line in f.readlines()]
NOMBRE_CYCLES_A_FAIRE = 1000000000
CAILLOU = 'O'
VIDE = '.'
Grille = list[list[str]]
def calc_north_load(grille: Grille) -> int :
""" Nord à gauche ! """
nb = 0
for ligne in grille:
for c,v in enumerate(ligne):
if v == CAILLOU:
nb += len(ligne) - c
return nb
def rotation_droite(grille: Grille) -> Grille:
return [ [ grille[len(grille)-1-r][c] for r in range(len(grille)) ]
for c in range(len(grille[0])) ]
def rotation_gauche(grille: Grille) -> Grille :
return [ [ grille[r][len(grille[0])-1-c] for r in range(len(grille)) ]
for c in range(len(grille[0])) ]
""" Plus agréable de déplacer les cailloux sur une même ligne
Donc on décide que le nord est à gauche et on tourne la grille au départ en conséquence """
def grille_penchee_a_gauche(grille: Grille) -> Grille:
return [ligne_penchee_a_gauche(ligne) for ligne in grille]
def ligne_penchee_a_gauche(ligne: MutableSequence[str]) -> MutableSequence[str]:
for c in range(len(ligne)):
if ligne[c] == CAILLOU:
ligne[c] = VIDE
for i in range(c,-1,-1):
if i == 0 or not ligne[i-1] == VIDE:
ligne[i] = CAILLOU
break
return ligne
def cycle(grille: Grille) -> Grille:
for _ in range(4):
grille = grille_penchee_a_gauche(grille)
grille = rotation_droite(grille)
return grille
grille: Grille = rotation_gauche([list(line) for line in lines]) # mettre le nord à gauche
solution_partie1 = calc_north_load(grille_penchee_a_gauche(grille))
anciennes_grilles: dict[str,int] = {} # stocke les indices en fonction de la repr. str de la grille
for nb_deja_faits in range(1, NOMBRE_CYCLES_A_FAIRE+1):
grille = cycle(grille)
ancien_nb_deja_faits = anciennes_grilles.get(str(grille), False)
if ancien_nb_deja_faits:
longueur_boucle = nb_deja_faits - ancien_nb_deja_faits
print(f"Trouvé boucle de longueur {longueur_boucle} après le {nb_deja_faits}e cycle.")
# On réduit ce qui reste à faire modulo la longueur du cycle de réapparition
reste_a_faire = (NOMBRE_CYCLES_A_FAIRE - nb_deja_faits) % longueur_boucle
for _ in range(reste_a_faire):
grille = cycle(grille)
break
else:
anciennes_grilles[str(grille)] = nb_deja_faits
print("Réponse partie 1:", solution_partie1)
print("Réponse partie 2:", calc_north_load(grille))