◂ 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
"""
Utilisation de tableaux numpy.array :
Surtout pratique pour faire une rotation, mais au final, prend deux fois plus de temps d'exécution !
"""
import numpy as np
from numpy import array
from numpy import typing as npt
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 = npt.NDArray[np.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 np.rot90(grille.transpose()).transpose()
# J'ai découvert après coup qu'on pouvait faire plutôt ça :
#return np.rot90(grille, 3)
def rotation_gauche(grille: Grille) -> Grille :
return np.rot90(grille)
# 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:
grille = grille.copy()
for row,ligne in enumerate(grille):
grille[row] = ligne_penchee_a_gauche(ligne)
return 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(array([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 index_actuel in range(NOMBRE_CYCLES_A_FAIRE):
grille = cycle(grille)
key = str(grille.tolist())
index_dejavu = anciennes_grilles.get(key, False)
if index_dejavu:
print(f"Trouvé cycle de longueur {index_actuel - index_dejavu} après le {index_actuel}e cycle.")
# On réduit ce qui reste à faire modulo la longueur du cycle de réapparition
reste_a_faire = (NOMBRE_CYCLES_A_FAIRE - 1 - index_actuel) % (index_actuel - index_dejavu)
for _ in range(reste_a_faire):
grille = cycle(grille)
break
else:
anciennes_grilles[key] = index_actuel
print("Réponse partie 1:", solution_partie1)
print("Réponse partie 2:", calc_north_load(grille))