advent-of-code/2021/python/day08.py

97 lines
2.2 KiB
Python
Raw Permalink Normal View History

2022-12-09 16:43:00 +00:00
import shared
from pprint import pp
from collections import defaultdict, Counter
ACTUAL = [
"abcefg", # 0
"cf", # 1 --- l2
"acdeg", # 2
"acdfg", # 3
"bcdf", # 4 ---l4
"abdfg", # 5
"abdefg", # 6
"acf", # 7 ---l3
"abcdefg", # 8 ---l7
"abcdfg", # 9
]
LENGTHS = list(map(len, ACTUAL))
SEGMENT_FREQ = {
"a": 8,
"b": 6,
"c": 8,
"d": 7,
"e": 4,
"f": 9,
"g": 7,
}
class Segments:
def __init__(self, name):
self.load(name)
def load(self, name):
self.lines = []
with open(name, "r") as f:
for line in f.readlines():
l = line.rstrip()
signals, output = l.split(" | ")
row = [signals.split(), output.split()]
self.lines.append(row)
def map(self, signals, output):
counts = Counter("".join(signals))
segments = {"a", "b", "c", "d", "e", "f", "g"}
segment_mapping = {}
for iw, c in SEGMENT_FREQ.items():
if c in (7, 8):
continue
for rw, rc in counts.items():
if rc == c:
segment_mapping[iw] = rw
lengths = {len(signal): set(signal) for signal in signals}
k1 = lengths[LENGTHS[1]]
k4 = lengths[LENGTHS[4]]
k7 = lengths[LENGTHS[7]]
segment_mapping["a"] = (k7 ^ k1).pop()
for wire in k1:
if wire not in segment_mapping.values():
segment_mapping["c"] = wire
for wire in k4:
if wire not in segment_mapping.values():
segment_mapping["d"] = wire
segment_mapping["g"] = (segments ^ set(segment_mapping.values())).pop()
wiring = {}
for num, ideal in enumerate(ACTUAL):
key = ""
for wire in ideal:
key += segment_mapping[wire]
key = "".join(sorted(key))
wiring[key] = str(num)
return wiring
def main():
s = Segments(shared.get_fname(8))
total = 0
for sig, out in s.lines:
wiring = s.map(sig, out)
display = ""
for digit in out:
display += wiring["".join(sorted(digit))]
total += int(display)
print(total)
if __name__ == "__main__":
main()