Advent of code

 15 décembre 2023 

  Lens Library : Suivre des instructions pour placer des lentilles dans des boites et changer leur distance focale
dcf=3,hp=9,kjfhxf-,hpmvrg-,pnb=7,zxz-,vrmt=4,ghrx=7,fz-,
  1. code_avec_classe.py
  2. code_avec_classe_hashmap.py
  3. code_sans_classe.py
from functools import reduce

Box = list["Lentille"]


class Lentille():
    # Attributs de classe
    __lentilles: dict[str,"Lentille"] = {}
    __boxes: list[Box] = [ [] for _ in range(256) ]

    __slots__ = ['__nom', 'focale', '__box']
    # Attributs d'instance
    __nom: str
    focale: int
    __box: Box

    @classmethod
    def get_lentille(cls, nom: str) -> "Lentille":
        lentille = Lentille.__lentilles.get(nom)
        if not lentille:
            lentille = Lentille(nom, -1)
        return lentille
    
    
    @classmethod
    def hash(cls, the_string: str) -> int:
        return reduce(lambda h,char: (h + ord(char)) * 17 % 256, the_string, 0)
    
    
    @classmethod
    def total_focusing_power(cls) -> int:
        return sum(lentille.focusing_power for lentille in Lentille.__lentilles.values())
    
    
    
    def __init__(self, nom: str, focale: int) -> None:
        if nom in Lentille.__lentilles:
            raise ValueError("Il existe déjà une lentille nommée " + nom)
        self.__nom = nom
        self.focale = focale
        self.__box = Lentille.__boxes[self.hash(nom)]
        Lentille.__lentilles[nom] = self
        
    def __str__(self):
        return f"Lentille {self.__nom} avec focale à {self.focale}"
    
    
    @property  # permet d'accéder au nom via « lentille.nom », mais empêche d'être modifié
    def nom(self):
        return self.__nom
        
    @property
    def box(self):
        return self.__box
    
    
    def remove_from_box(self) -> None:
        if self in self.box:
            self.box.remove(self)

    def put_in_box(self) -> None:
        if self not in self.box:
            self.box.append(self)
            
    
    @property
    def focusing_power(self) -> int:
        if self not in self.box:
            return 0
        return (Lentille.__boxes.index(self.box)+1) * (self.box.index(self) + 1) * self.focale
    
                                     
        
instructions = open('input.txt', 'r', encoding='utf-8').read().strip().split(',')
reponse_partie_1 = sum(map(Lentille.hash, instructions))


for instruction in instructions:
    if instruction.endswith('-'):
        nom = instruction[:-1]
        Lentille.get_lentille(nom).remove_from_box()
    else:
        nom, chiffre = instruction.split('=')
        lentille = Lentille.get_lentille(nom)
        lentille.focale = int(chiffre)
        lentille.put_in_box()               
           
        
print("Réponse partie 1:", reponse_partie_1)
print("Réponse partie 2:", Lentille.total_focusing_power())