Coverage for Day3 / part2.py: 100%
22 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-12 09:47 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-12 09:47 +0000
1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
4"""
5Advent Of Code 2025
6===================
7Day : 3
8Part : 2
10Ce script extrait, pour chaque identifiant numérique, la plus grande
11sous-séquence possible de longueur fixée tout en respectant l’ordre
12d’apparition des chiffres.
14L’objectif est d’optimiser la valeur numérique obtenue en conservant
15exactement `n` digits parmi ceux présents dans l’identifiant d’origine.
17.. codeauthor:: Alexandre Condette <alexandre.condette@wanadoo.fr>
18"""
20# %% ========================================================================
21# Imports
23# ===========================================================================
25# %% ========================================================================
26# Input data
27def get_input(day: int = 1, example: bool = False) -> list:
28 """
29 Lit le fichier d'input pour le jour donné.
31 :param day: numéro du jour AOC
32 :param example: si True, utilise le fichier example.txt sinon input.txt
33 :return: liste de lignes du fichier
34 :rtype: list
35 """
36 file = 'example.txt' if example else 'input.txt'
37 with open(f"./Day{day}/{file}", 'r', encoding='utf-8') as f:
38 return f.readlines()
40# ===========================================================================
42# %% ========================================================================
43# Résolution
44def max_subsequence_as_number(digits: list, n: int) -> int:
45 """
46 Détermine la plus grande sous-séquence possible de longueur `n`
47 en conservant l’ordre d’apparition des digits.
49 On utilise ici une approche de type « monotonic stack » :
50 - On sait combien de digits on peut supprimer : `m - n`
51 - On construit une pile où chaque nouveau digit pousse les précédents
52 plus petits, tant qu’on peut encore en retirer.
53 - Le résultat final est simplement les `n` premiers digits de la pile.
55 :param digits: liste de chiffres extraits de la ligne
56 :param n: longueur de la sous-séquence maximale à conserver
57 :return: le nombre entier formé par la sous-séquence maximale
58 :rtype: int
59 """
60 m = len(digits)
62 # Nombre total de suppressions possibles pour atteindre n digits
63 remove = m - n
64 stack = []
65 for d in digits:
66 # Tant qu'on peut supprimer, et que le digit précédent est plus petit,
67 # on le retire pour laisser place à un chiffre plus grand.
68 while stack and remove > 0 and stack[-1] < d:
69 stack.pop()
70 remove -= 1
72 # On empile le digit courant dans la séquence
73 stack.append(d)
75 # S'il reste des suppressions non utilisées,
76 # on coupe simplement la fin de la pile.
77 final = stack[:n]
79 # Construction du nombre final
80 return int("".join(str(d) for d in final))
82# ---------------------------------------------------------------------------
83def solve(data: list, n: int = 12) -> int:
84 """
85 Calcule la somme des plus grandes sous-séquences pour chaque ligne d’input.
87 Pour chaque ligne :
88 - Nettoyage du texte
89 - Conversion en liste de digits
90 - Extraction de la meilleure sous-séquence possible (length = n)
91 - Accumulation du total
93 :param data: lignes du fichier d’entrée
94 :param n: longueur des sous-séquences à conserver
95 :return: somme des valeurs trouvées
96 :rtype: int
97 """
98 joltage = 0
99 for line in data:
100 line = line.strip()
101 digits = [int(d) for d in line]
103 joltage += max_subsequence_as_number(digits, n)
105 return joltage
107# ===========================================================================
109# %%
110if __name__ == "__main__":
111 RESULT = solve(get_input(3, False), 12)
113 print("\n" + "═" * 60)
114 print(" 🔐 Advent of Code 2025 — Day 3 | Part 2".center(60))
115 print("═" * 60)
116 print(f"Joltage trouvé : \033[96m{RESULT}\033[0m")
117 print("═" * 60 + "\n")