Advent of Code 2025
2025-12-06
Puzzle: https://adventofcode.com/2025/day/6
Je n’ai pas trop aimé celui-ci, donc on va faire court. C’est principalement du bidouillage à faire sur les entrées pour les mettre dans le bon ordre, mais à part ça il n’y a pas trop à réfléchir.
On doit trouver la solution d’opérations mathématiques simples, mais dont les opérateurs et les opérandes sont arrangés un peu bizarrement.
123 328 51 64
45 64 387 23
6 98 215 314
* + * +
Pour la première partie, on applique l’opérateur sur tous les nombres
de la colonne. Donc: 123*45*6, 328+64+98, etc.
On doit ensuite calculer la somme de tous les résultats des
opérations.
Première étape: séparer les lignes, et dans chaque ligne couper sur
les espaces. La fonction split de Python est pratique pour
ça, car par défaut elle coupe sur tout ce qui est “whitespace”: espace
simple, espaces multiples, tabulations… Pas besoin donc d’une logique
compliquée.
def prepare_data(data: str) -> list[tuple[str]]:
table = [d.split() for d in data.split('\n')]
# ...À ce stade, on a un tableau à deux dimensions, mais on veut faire les
opérations par colonne. Pour se faciliter la vie, on peut transposer le
tableau pour que les colonnes deviennent des lignes, et vice-versa. Un
truc rapide pour faire ça en Python est d’utiliser une combinaison de
* (l’opérateur d’unpacking) et zip (pour
parcourir plusieurs listes en parallèle):
def prepare_data(data: str) -> list[tuple[str]]:
table = [d.split() for d in data.split('\n')]
return list(zip(*table))*table va séparer notre tableau en lignes (équivalent de
faire table[0], table[1], ...), et zip va
permettre de d’abord regarder le premier élément de chaque ligne, puis
le second, etc. zip donne un générateur, qu’on reconvertit
en list.
Après ça, on a:
[('123', '45', '6', '*'), ('328', '64', '98', '+'), ('51', '387', '215', '*'), ('64', '23', '314', '+')],
et nos opérandes sont bien rassemblés avec nos opérateurs, qui sont
toujours le dernier élément de la liste. Pour effectuer les opérations,
on sépare les opérandes et l’opérateur, et on peut utiliser functools.reduce
pour appliquer cumulativement l’opérateur aux opérandes. Il nous faut
juste convertir les string soit en entiers, soit en
fonction:
fns = {
'*': lambda x, y: x*y,
'+': lambda x, y: x+y,
'-': lambda x, y: x-y,
'/': lambda x, y: x/y
}
def operate(op: tuple[str]) -> int:
operands, operator = op[:-1], op[-1]
return reduce(fns[operator], [int(x) for x in operands])Et dans le main, on peut appliquer cette opération à
chaque ligne de données, et sommer les résultats:
def main():
data = load_input(6, '_sample', prepare_data)
print(f"Part 1: {sum(operate(d) for d in data)}")Pour la seconde partie, on doit lire les opérations un peu différemment. Maintenant, les nombres eux-mêmes sont écrits de haut en bas. Donc notre exemple:
123 328 51 64
45 64 387 23
6 98 215 314
* + * +
Doit maintenant se lire: 1*24*356,
369+248+8, etc.
On doit donc traiter les données un peu différemment. On récupère notre tableau en séparant tous les caractères, et pas sur les whitespace. On le transpose comme avant, et on supprime les espaces.
def prepare_data_2(data: str) -> list[str]:
table = [[c for c in row] for row in data.split('\n')]
table = list(zip(*table))
table = [''.join(t).replace(' ', '') for t in table]
return tableCa nous donne une liste:
['1*', '24', '356', '', '369+', '248', '8', '', '32*', '581', '175', '', '623+', '431', '4']
Dans cette liste, on sait que chaque opération est séparée par un
'', et contient l’opérateur à la fin d’un nombre. Dans
l’exemple ici c’est à chaque fois le premier, mais je n’ai pas trop
envie de vérifier que c’est le cas partout dans le vrai input, donc on
va être un peu plus général:
def part2(data: list[str]) -> int:
operands = []
operator = None
total = 0
for s in data:
if s == '':
total += reduce(fns[operator], operands)
operands = []
operator = None
continue
if s[-1] in fns.keys():
operator = s[-1]
operands.append(int(s[:-1]))
else:
operands.append(int(s))
total += reduce(fns[operator], operands)
return totalDès qu’on trouve un '', on applique l’opération sur les
éléments précédents, qu’on convertit au fur et à mesure en opérandes
entières et opérateurs. Dans le main:
def main():
# ...
data2 = load_input(6, '_sample', prepare_data_2)
print(f"Part 2: {part2(data2)}")Et on y est.