• [^] # Re: Pas bien compliqué... en reformulant

    Posté par (site web personnel) . En réponse au message Advent of Code, jour 13. Évalué à 3.

    Allez, voici le code :

    from collections.abc import Iterable
    from typing import Optional, Self
    from enum import Enum
    import io
    import aoc
    Coords = tuple[int, int]
    class Terrain(Enum):
     ASH = '.'
     ROCK = '#'
     def __str__(self) -> str:
     if self is self.ASH:
     return ' '
     if self is self.ROCK:
     return '▒'
     raise ValueError('invalid terrain value')
    class Pattern:
     def __init__(self, array: Iterable[Iterable[Terrain]]):
     self.matrix = list(list(line) for line in array)
     self.ly = len(self.matrix)
     self.lx = len(self.matrix[0])
     @classmethod
     def import_lines(cls, lines: Iterable[str]) -> Self:
     return cls((Terrain(char) for char in line.rstrip()) for line in lines)
     def __getitem__(self, coords: Coords) -> Terrain:
     y, x = coords
     return self.matrix[y][x]
     def __str__(self) -> str:
     s = io.StringIO()
     for line in self.matrix:
     for terrain in line:
     s.write(str(terrain))
     s.write('\n')
     return s.getvalue()
     def y_reflection_errors(self, y: int) -> int:
     """Count the number of errors in a horizontal reflection between y - 1
     and y. Return 0, 1 or 2 (meaning many)."""
     errors = 0
     for i in range(min(y, self.ly - y)):
     y1 = y - 1 - i
     y2 = y + i
     for x in range(self.lx):
     errors += self[y1, x] != self[y2, x]
     if errors >= 2:
     return errors
     return errors
     def x_reflection_errors(self, x: int) -> int:
     """Count the number of errors in a vertical reflection between x - 1
     and x. Return 0, 1 or 2 (meaning many)."""
     errors = 0
     for i in range(min(x, self.lx - x)):
     x1 = x - 1 - i
     x2 = x + i
     for y in range(self.ly):
     errors += self[y, x1] != self[y, x2]
     if errors >= 2:
     return errors
     return errors
     def y_reflection1(self) -> Optional[int]:
     for y in range(1, self.ly):
     if self.y_reflection_errors(y) == 0:
     return y
     return None
     def x_reflection1(self) -> Optional[int]:
     for x in range(1, self.lx):
     if self.x_reflection_errors(x) == 0:
     return x
     return None
     def y_reflection2(self) -> Optional[int]:
     for y in range(1, self.ly):
     if self.y_reflection_errors(y) == 1:
     return y
     return None
     def x_reflection2(self) -> Optional[int]:
     for x in range(1, self.lx):
     if self.x_reflection_errors(x) == 1:
     return x
     return None
    def part1(lines: aoc.Data) -> int:
     """Solve puzzle part 1: determine the sum of perfect reflection columns and
     ×ばつ that of perfect reflection lines."""
     total = 0
     for i, group in enumerate(aoc.group_lines(lines)):
     pattern = Pattern.import_lines(group)
     if (x := pattern.x_reflection1()) is not None:
     total += x
     elif (y := pattern.y_reflection1()) is not None:
     total += 100 * y
     else:
     raise ValueError('pattern without reflection‽')
     return total
    def part2(lines: aoc.Data) -> int:
     """Solve puzzle part 1: determine the sum of imperfect reflection columns
     and ×ばつ that of imperfect reflection lines."""
     total = 0
     for i, group in enumerate(aoc.group_lines(lines)):
     pattern = Pattern.import_lines(group)
     if (x := pattern.x_reflection2()) is not None:
     total += x
     elif (y := pattern.y_reflection2()) is not None:
     total += 100 * y
     else:
     raise ValueError('pattern without reflection‽')
     return total