Coverage for Day7 / part1.py: 80%

38 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 : 7 

8Part : 1 

9 

10Ce script simule la propagation d’un faisceau lumineux depuis un point 

11d’entrée marqué par 'S'. Le faisceau descend ligne par ligne. 

12 

13Lorsque le faisceau rencontre un splitter '^', il : 

14 - compte une occurrence, 

15 - se divise en deux faisceaux (gauche et droite). 

16 

17Les faisceaux continuent leur propagation jusqu’à la fin de la carte ou 

18jusqu’à ce qu’aucun faisceau ne reste actif. 

19 

20Le résultat correspond au nombre total de splitters traversés. 

21 

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

23""" 

24 

25 

26# %% ======================================================================== 

27# Input data 

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

29 """ 

30 Lit le fichier d'entrée pour le jour donné. 

31 

32 :param day: numéro du jour AoC 

33 :param example: True pour example.txt, False pour input.txt 

34 :return: liste des lignes du fichier 

35 """ 

36 filename = 'example.txt' if example else 'input.txt' 

37 with open(f"./Day{day}/{filename}", '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 Simule les faisceaux descendants depuis 'S' et compte les splitters '^'. 

47 

48 :param data: liste de lignes décrivant la carte 

49 :return: nombre total de splitters rencontrés 

50 """ 

51 

52 # Préparation des lignes 

53 rows = [line.rstrip("\n") for line in data] 

54 height = len(rows) 

55 if height == 0: 55 ↛ 56line 55 didn't jump to line 56 because the condition on line 55 was never true

56 return 0 

57 

58 width = max(len(r) for r in rows) 

59 grid = [r.ljust(width, " ") for r in rows] 

60 

61 # Recherche de la position de 'S' 

62 start_row = start_col = None 

63 for i, row in enumerate(grid): 63 ↛ 69line 63 didn't jump to line 69 because the loop on line 63 didn't complete

64 if "S" in row: 64 ↛ 63line 64 didn't jump to line 63 because the condition on line 64 was always true

65 start_row = i 

66 start_col = row.index("S") 

67 break 

68 

69 if start_row is None: 69 ↛ 70line 69 didn't jump to line 70 because the condition on line 69 was never true

70 raise ValueError("Point d'entrée 'S' introuvable dans l'input") 

71 

72 splits = 0 

73 

74 # Faisceaux actifs (colonnes) 

75 active_beams = {start_col} 

76 

77 # Propagation ligne par ligne 

78 for r in range(start_row + 1, height): 

79 next_beams = set() 

80 

81 for c in active_beams: 

82 if c < 0 or c >= width: 82 ↛ 83line 82 didn't jump to line 83 because the condition on line 82 was never true

83 continue 

84 

85 ch = grid[r][c] 

86 

87 # Splitter : deux faisceaux + comptage 

88 if ch == "^": 

89 splits += 1 

90 if c - 1 >= 0: 90 ↛ 92line 90 didn't jump to line 92 because the condition on line 90 was always true

91 next_beams.add(c - 1) 

92 if c + 1 < width: 92 ↛ 81line 92 didn't jump to line 81 because the condition on line 92 was always true

93 next_beams.add(c + 1) 

94 

95 else: 

96 # Le faisceau continue 

97 next_beams.add(c) 

98 

99 if not next_beams: 99 ↛ 100line 99 didn't jump to line 100 because the condition on line 99 was never true

100 break 

101 

102 active_beams = next_beams 

103 

104 return splits 

105 

106# =========================================================================== 

107 

108# %% 

109if __name__ == "__main__": 

110 RESULT = solve(get_input(7, False)) 

111 

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

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

114 print("═" * 60) 

115 print(f"Résultat : \033[96m{RESULT}\033[0m") 

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