Coverage for Day5 / part2.py: 100%

19 statements  

« 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 -*- 

3 

4""" 

5Advent Of Code 2025 

6=================== 

7Day : 5 

8Part : 2 

9 

10Ce script calcule le nombre total d'identifiants présents dans l'ensemble  

11des intervalles définis dans la première section de l'input. 

12 

13Chaque intervalle est défini sous la forme "start-stop". La solution ne  

14génère pas tous les identifiants individuellement ; elle fusionne les  

15intervalles qui se chevauchent ou sont contigus, puis calcule la somme  

16des longueurs des intervalles fusionnés pour obtenir le résultat final. 

17 

18Cette approche permet de gérer efficacement un très grand nombre de valeurs  

19sans explosion mémoire. 

20 

21.. codeauthor:: Alexandre Condette <alexandre.condette@wanadoo.fr> 

22""" 

23 

24 

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é. 

30 

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 [line.rstrip('\n') for line in f] 

39 

40# =========================================================================== 

41 

42# %% ======================================================================== 

43# Résolution 

44def solve(data: list) -> int: 

45 """ 

46 Calcule le nombre total d'identifiants inclus dans les intervalles. 

47 

48 L'input est supposé structuré avec : 

49 - Une première section contenant des intervalles "start-stop". 

50 - Une section suivante contenant éventuellement d'autres informations 

51 ou identifiants, qui sont ignorés dans cette partie. 

52 

53 Étapes principales : 

54 1. Extraction de tous les intervalles. 

55 2. Tri des intervalles par début. 

56 3. Fusion des intervalles qui se chevauchent ou sont contigus. 

57 4. Somme des longueurs des intervalles fusionnés pour obtenir le total. 

58 

59 :param data: Liste brute des lignes du fichier. 

60 :return: Nombre total d'identifiants présents dans les intervalles. 

61 :rtype: int 

62 """ 

63 intervals: list = [] 

64 

65 # 1. Collecte uniquement les intervalles 

66 for line in data: 

67 if "-" in line: 

68 start, stop = map(int, line.split("-")) 

69 intervals.append((start, stop)) 

70 else: 

71 continue # On arrête à la fin de la section des intervalles 

72 

73 # 2. Tri des intervalles 

74 intervals.sort() 

75 

76 # 3. Fusion des intervalles 

77 merged = [] 

78 for start, stop in intervals: 

79 if not merged or start > merged[-1][1] + 1: 

80 merged.append([start, stop]) 

81 else: 

82 merged[-1][1] = max(merged[-1][1], stop) 

83 

84 # 4. Calcul du nombre total d'identifiants 

85 fresh = sum(stop - start + 1 for start, stop in merged) 

86 

87 return fresh 

88 

89# =========================================================================== 

90 

91# %% 

92if __name__ == "__main__": 

93 RESULT = solve(get_input(5, False)) 

94 

95 print("\n" + "═" * 60) 

96 print(" 🔐 Advent of Code 2025 — Day 5 | Part 2".center(60)) 

97 print("═" * 60) 

98 print(f"Ingrédients frais : \033[96m{RESULT}\033[0m") 

99 print("═" * 60 + "\n")