• # En Python

    Posté par (site web personnel) . En réponse au message Avent du Code, jour 5. Évalué à 3. Dernière modification le 05 décembre 2022 à 11:37.

    Ce qui est assez casse-pied dans ce problème, c'est que les données d'entrées sont dans un ordre qui est optimisé pour la lecture par un lutin grutier ou en l'occurrence une lutine grutière.

    Bref, voici le code :

    import re
    from collections import deque
    from io import StringIO
    from typing import Dict, List, Iterable, Iterator, MutableSequence, Sequence
    from typing_extensions import Protocol
    class Crane(Protocol):
     def load(self, stacks: Sequence[MutableSequence[str]],
     labels: Iterable[str]) -> None:
     ...
     def move(self, orig: str, dest: str, n: int) -> None:
     ...
     def top(self) -> str:
     ...
    class CrateMover:
     def __init__(self) -> None:
     self.stacks = {} # type: Dict[str, MutableSequence[str]]
     self.labels = [] # type: List[str]
     def load(self, stacks: Sequence[MutableSequence[str]],
     labels: Iterable[str]) -> None:
     for stack, label in zip(stacks, labels):
     self.stacks[label] = stack
     for label in labels:
     self.labels.append(label)
     def top(self) -> str:
     result = StringIO()
     for label in self.labels:
     result.write(self.stacks[label][-1])
     return result.getvalue()
    class CrateMover9000(CrateMover):
     def __init__(self, *args, **kwargs) -> None:
     super().__init__()
     def move(self, orig: str, dest: str, n: int) -> None:
     orig_stack = self.stacks[orig]
     dest_stack = self.stacks[dest]
     for _ in range(n):
     dest_stack.append(orig_stack.pop())
    class CrateMover9001(CrateMover):
     def __init__(self, *args, **kwargs) -> None:
     super().__init__()
     def move(self, orig: str, dest: str, n: int) -> None:
     orig_stack = self.stacks[orig]
     dest_stack = self.stacks[dest]
     temp_stack = deque() # type: deque[str]
     for _ in range(n):
     temp_stack.appendleft(orig_stack.pop())
     dest_stack.extend(temp_stack)
    def solve(lines: Iterator[str], crane: Crane) -> str:
     re_crates = re.compile(r'^\s*\[')
     stacks = [] # type: List[deque[str]]
     # First lines are crate stack descriptions
     for line in lines:
     if re_crates.match(line):
     # This line describes stacked crates
     for i, label in enumerate(line[1:len(line):4]):
     if i >= len(stacks):
     stacks.append(deque())
     stack = stacks[i]
     if label != ' ':
     stack.appendleft(label)
     else:
     # This line provides the labels of crate stacks
     break
     # Current line provides the labels of crate stacks
     labels = line[1:len(line):4]
     # We have enough data to load the crane with crate stacks
     crane.load(stacks, labels)
     # Next line is a blank one
     s = next(lines)
     # Next lines are crate moving instructions
     re_instruction = re.compile(r'^move (\d+) from (.) to (.)$')
     for line in lines:
     m = re_instruction.match(line)
     if m is None:
     raise ValueError("unrecognized input line")
     n = int(m.group(1))
     orig = m.group(2)
     dest = m.group(3)
     crane.move(orig, dest, n)
     return crane.top()
    def part1(data: Iterable[str]) -> str:
     crane = CrateMover9000()
     return solve(iter(data), crane)
    def part2(data: Iterable[str]) -> str:
     crane = CrateMover9001()
     return solve(iter(data), crane)