88 lines
2.1 KiB
Python
88 lines
2.1 KiB
Python
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}")
|