import itertools import os import sys VERBOSE = os.getenv("AOC_VERBOSE") == "True" digits = { "abcefg": 0, "cf": 1, "acdeg": 2, "acdfg": 3, "bcdf": 4, "abdfg": 5, "abdefg": 6, "acf": 7, "abcdefg": 8, "abcdfg": 9, } lines = sys.stdin.read().splitlines() # part 1 lengths = {len(k) for k, v in digits.items() if v in (1, 4, 7, 8)} answer_1 = sum( len(p) in lengths for line in lines for p in line.split("|")[1].strip().split() ) print(f"answer 1 is {answer_1}") # 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] if VERBOSE: print(value) values.append(value) answer_2 = sum(values) print(f"answer 2 is {answer_2}")