Coverage for Day2 / part1.py: 100%

24 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 : 2 

8Part : 1 

9 

10Ce script identifie tous les identifiants "invalides" dans une liste  

11de plages numériques. Un ID est invalide s'il est composé de deux fois  

12la même séquence de chiffres (ex : 12 → 1212, 345 → 345345). 

13 

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

15""" 

16 

17# %% ======================================================================== 

18# Imports 

19from math import ceil, floor 

20# =========================================================================== 

21 

22# %% ======================================================================== 

23# Input data 

24def get_input(day: int = 1, example: bool = False) -> list: 

25 """ 

26 Lit le fichier d'input pour le jour donné. 

27 

28 :param day: numéro du jour AOC 

29 :param example: si True, utilise le fichier example.txt sinon input.txt 

30 :return: liste de lignes du fichier 

31 :rtype: list 

32 """ 

33 file = 'example.txt' if example else 'input.txt' 

34 with open(f"./Day{day}/{file}", 'r', encoding='utf-8') as f: 

35 return f.read() 

36 

37# =========================================================================== 

38 

39# %% ======================================================================== 

40# Résolution 

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

42 """ 

43 Calcule la somme de tous les identifiants invalides dans les plages spécifiées. 

44 

45 Une plage a la forme "A-B". Un ID est considéré invalide si sa 

46 représentation est constituée de *deux fois* la même séquence de chiffres : 

47 - 11 → invalide (1 répété deux fois) 

48 - 1212 → invalide (12 répété deux fois) 

49 - 9999 → invalide (99 répété deux fois) 

50 - etc. 

51 

52 Optimisation : 

53 - Plutôt que de tester chaque nombre : on détecte mathématiquement 

54 toutes les valeurs ayant le pattern s * m où m = 10^k + 1. 

55 

56 :param data: Chaîne contenant plusieurs plages, séparées par des virgules. 

57 :return: Somme de tous les identifiants invalides présents dans les plages. 

58 :rtype: int 

59 """ 

60 invalid_id: int = 0 

61 all_ids = data.split(",") 

62 

63 for ids in all_ids: 

64 # Extraction bornes [start, stop] 

65 start, stop = ids.split('-') 

66 start = int(start) 

67 stop = int(stop) + 1 # inclure la borne supérieure 

68 

69 # Kmax = nombre max de digits pour les patterns divisés en deux (ex: 1234 → k=2) 

70 Kmax = floor(len(str(stop)) / 2) 

71 

72 for k in range(1, Kmax + 1): 

73 # m = 10^k + 1 → génère les nombres duplicables (ex : k=2 → 101 → s * 101 = ss) 

74 m = 10 ** k + 1 

75 

76 # On cherche les valeurs s telles que s*m tombe dans [start, stop] 

77 s_lo = ceil(start / m) 

78 s_hi = floor(stop / m) 

79 

80 # Restreindre s aux nombres k-digits 

81 s_lo = max(s_lo, 10 ** (k - 1)) 

82 s_hi = min(s_hi, 10 ** k - 1) 

83 

84 # Si la borne basse dépasse la borne haute → aucune valeur possible 

85 if s_lo <= s_hi: 

86 # Nombre de valeurs possibles 

87 count = s_hi - s_lo + 1 

88 # Somme des s du range 

89 sum_s = (s_lo + s_hi) * count // 2 

90 # Contribution total = m * somme(s) 

91 invalid_id += m * sum_s 

92 

93 return invalid_id 

94 

95# =========================================================================== 

96 

97# %% 

98if __name__ == "__main__": 

99 RESULT = solve(get_input(2, False)) 

100 

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

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

103 print("═" * 60) 

104 print(f"ID Invalides trouvés : \033[96m{RESULT}\033[0m") 

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