Пример #1
0
def part_2(values: Iterable[int]) -> int:
    """
    Considering every single measurement isn't as useful as you expected: there's just too much
    noise in the data.

    Instead, consider sums of a **three-measurement sliding window**. Again considering the above
    example:

        >>> measurements = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263]
        >>> [sum(w) for w in slidingw(measurements, 3)]
        [607, 618, 618, 617, 647, 716, 769, 792]

    In this example, there are **5** sums that are larger than the previous sum.

        >>> count_increases(_)
        5

    Consider sums of a three-measurement sliding window.
    **How many sums are larger than the previous sum?**

        >>> part_2(measurements)
        part 2: 5 increases
        5
    """

    triples = (sum(w) for w in slidingw(values, 3))
    result = count_increases(triples)

    print(f"part 2: {result} increases")
    return result
Пример #2
0
 def shortest_path(self, start_at: str = '0') -> tuple[int, Path]:
     distances = self.calculate_distances()
     result_path, distance = mink(
         self.paths(start_at),
         key=lambda path: sum(distances[(a, b)]
                              for a, b in slidingw(path, 2)))
     return distance, result_path
Пример #3
0
def draw_arrangement(arrangement: list[str], rules: Rules) -> None:
    assert len(arrangement) > 1

    seats = arrangement[-1:] + arrangement[:-1]
    for neighbor_1, seat, neighbor_2 in slidingw(seats, 3, wrap=True):
        happines_1 = rules[seat, neighbor_1]
        happines_2 = rules[seat, neighbor_2]
        print(f"{happines_1:+3} {seat:5} {happines_2:+3}")
Пример #4
0
 def shortest_closed_path(self, start_at: str = '0') -> tuple[int, Path]:
     distances = self.calculate_distances()
     result_path, (distance, _) = mink(
         self.closed_paths(start_at),
         # path is included in key in order to make the calculation deterministic
         # because closed path can be reversed (0-1-2-0 and 0-2-1-0)
         key=lambda path:
         (sum(distances[(a, b)] for a, b in slidingw(path, 2)), path))
     return distance, result_path
Пример #5
0
def grow(polymer: str, rules: Rules, steps: int, log: bool = False) -> str:
    assert len(polymer) >= 2

    if log:
        print(f'Template:     {polymer}')

    for step in range(steps):
        polymer = ''.join(
            e
            for i0, i1 in slidingw(polymer, 2)
            for e in (i0, rules[(i0, i1)])
        ) + polymer[-1]

        if log:
            print(f'After step {step + 1}: {polymer}')

    return polymer
Пример #6
0
def _parse_line_fixes(line: str, *fixes: str) -> tuple[str, ...]:
    assert len(fixes) >= 2

    results = []

    for fix1, fix2 in slidingw(fixes, 2):
        assert line.startswith(fix1), (line, fix1)
        line = line[len(fix1):]
        if fix2:
            pos2 = line.index(fix2)
            results.append(line[:pos2])
            line = line[pos2:]
        else:
            results.append(line)
            line = ''

    assert line == fixes[-1], f"{line!r} != {fixes[-1]!r}"
    return tuple(results)
Пример #7
0
def grow_optimized(polymer: str, rules: Rules, steps: int) -> Counter[str]:
    assert len(polymer) >= 2

    # instead of keeping track of the polymer itself, we'll watch only counts of its pairs
    pairs = Counter(slidingw(polymer, 2))

    for _ in range(steps):
        pairs = _total_counts(
            (new_pair, count)
            for (i0, i1), count in pairs.items()
            if (out := rules[(i0, i1)])
            for new_pair in [(i0, out), (out, i1)]
        )

    return _total_counts(
        chain(
            # sum of pair quantities -> only first element (otherwise result would be ~doubled)
            ((e0, count) for (e0, _), count in pairs.items()),
            # plus 1 for the last element (which remains unchanged throughout the process)
            [(polymer[-1], 1)]
        )
    )
Пример #8
0
def count_increases(values: Iterable[int]) -> int:
    return sum(v1 > v0 for v0, v1 in slidingw(values, 2))
Пример #9
0
def captcha_1(digits: str) -> int:
    return sum(
        int(a)
        for a, b in slidingw(digits, 2, wrap=True)
        if a == b
    )