import itertools from typing import Any, Iterator from ..base import BaseSolver digits = { "abcefg": 0, "cf": 1, "acdeg": 2, "acdfg": 3, "bcdf": 4, "abdfg": 5, "abdefg": 6, "acf": 7, "abcdefg": 8, "abcdfg": 9, } class Solver(BaseSolver): def solve(self, input: str) -> Iterator[Any]: lines = input.splitlines() # part 1 lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)} yield sum( len(p) in lengths for line in lines for p in line.split("|")[1].strip().split() ) # part 2 values: list[int] = [] for line in lines: parts = line.split("|") broken_digits = sorted(parts[0].strip().split(), key=len) per_length = { k: list(v) for k, v in itertools.groupby(sorted(broken_digits, key=len), key=len) } # a can be found immediately a = next(u for u in per_length[3][0] if u not in per_length[2][0]) # c and f have only two possible values corresponding to the single entry of # length 2 cf = list(per_length[2][0]) # the only digit of length 4 contains bcdf, so we can deduce bd by removing cf bd = [u for u in per_length[4][0] if u not in cf] # the 3 digits of length 5 have a, d and g in common adg = [ u for u in per_length[5][0] if all(u in pe for pe in per_length[5][1:]) ] # we can remove a dg = [u for u in adg if u != a] # we can deduce d and g d = next(u for u in dg if u in bd) g = next(u for u in dg if u != d) # then b b = next(u for u in bd if u != d) # f is in the three 6-length digits, while c is only in 2 f = next(u for u in cf if all(u in p for p in per_length[6])) # c is not f c = next(u for u in cf if u != f) # e is the last one e = next(u for u in "abcdefg" if u not in {a, b, c, d, f, g}) mapping = dict(zip((a, b, c, d, e, f, g), "abcdefg")) value = 0 for number in parts[1].strip().split(): digit = "".join(sorted(mapping[c] for c in number)) value = 10 * value + digits[digit] self.logger.info(f"value for '{line}' is {value}") values.append(value) yield sum(values)