Advent of Code: Day 8
Oh man, Day 8 is hard.
Part 1
You're given a seven-segment display. That's the numbers on your digital clock, each one formed by some segments. However, the segments are all mixed up, so you'll need to demix them somehow.
For the input, you're given the list of all digits that are now represented by the mixed up segments. However, the mixup itself is consistent for all digits. Now if we pay careful attention, we will realize that the digits 1, 4, 7, and 8 each has a unique number of segments. So for Part 1, calculate how many times these 4 digits appear.
It's just a simple counting problem, so here's my Python code:
def read(filename):
file = open(filename)
lines = file.read().splitlines()
entries = []
for line in lines:
fields = line.split(' | ')
left = fields[0]
right = fields[1]
segments = left.split()
digits = right.split()
entries.append([segments, digits])
return entries
def solve(entries):
# Count unique digits
count = 0
for entry in entries:
digits = entry[1]
for digit in digits:
if len(digit) in [2, 4, 3, 7]:
count += 1
print(digit)
print(count)
entries = read('input.txt')
solve(entries)
Part 2: The Real Monster
After Part 1, the real problem appears. In the input, you're also given a 4-digit number for each line. Of course, each has segments mixed up like before. Now, use analysis to decode these numbers then add them up.
This took me one full day to complete, not gonna lie.
After a lot of thinking, I found that we could reuse part of Part 1. Basically, now we know what 1, 4, 7, 8 look like. Notice that if we take the segments of 7 and subtract 1's segments, we now get the segment a
left. And that's our first segment decoded!
Next, for each entry, if we count the number of times a segment appears in the digits from 0 to 9, we will have these unique situations:
Segment
b
appears exactly 6 timesSegment
e
appears exactly 4 timesSegment
f
appears exactly 9 times
So this gives us another 3 segments decoded. Also, some pairs of segments appear the same number of times too:
Segments
a
andc
appear exactly 8 timesSegments
d
andg
appear exactly 7 times
For ac
, since we already knew a
from before, we can easily deduct segment c
.
Now, if we subtract 7's segments from 4's, we have two segments of bd
. Coupled with the segments dg
above, we can find the only segment d
that satisfies two criteria. The only segment left, g
must be the remaining one.
As usual, below is my solution code. Please excuse its length:
def read(filename):
file = open(filename)
lines = file.read().splitlines()
entries = []
for line in lines:
fields = line.split(' | ')
left = fields[0]
right = fields[1]
digits = left.split()
outputs = right.split()
entries.append([digits, outputs])
return entries
def parse_digit(dictionary, mixed_digit):
a = dict()
a['abcefg'] = 0
a['cf'] = 1
a['acdeg'] = 2
a['acdfg'] = 3
a['bcdf'] = 4
a['abdfg'] = 5
a['abdefg'] = 6
a['acf'] = 7
a['abcdefg'] = 8
a['abcdfg'] = 9
segments = [dictionary[mixed_segment] for mixed_segment in mixed_digit]
segments.sort()
return a[''.join(segments)]
def solve(entries):
# create dictionary(a -> b) and digits([0] = 'ab')
dictionary = dict()
digits = [''] * 10
total = 0
for entry in entries:
mixed_digits, outputs = entry
# Determine unique digits
digits[1] = [digit for digit in mixed_digits if len(digit) == 2][0]
digits[7] = [digit for digit in mixed_digits if len(digit) == 3][0]
digits[4] = [digit for digit in mixed_digits if len(digit) == 4][0]
digits[8] = [digit for digit in mixed_digits if len(digit) == 7][0]
# Determine segment a from 7 - 1
a = list(set(digits[7]) - set(digits[1]))[0]
dictionary[a] = 'a'
# Count characters
character_count = dict()
for char in 'abcdefg':
character_count[char] = 0
for digit in mixed_digits:
for char in digit:
character_count[char] += 1
# Determine character maps
ac, dg = [], []
for char in 'abcdefg':
match character_count[char]:
case 6:
dictionary[char] = 'b'
case 4:
dictionary[char] = 'e'
case 9:
dictionary[char] = 'f'
case 8: # could be either a or c
ac.append(char)
case 7: # could be either d or g
dg.append(char)
# Determine a and c
# c = ac - a
dictionary[list(set(ac) - set(a))[0]] = 'c'
# Determine d and g
# d exists in bd = 4 - 1
bd = set(digits[4]) - set(digits[1])
if dg[0] in bd:
dictionary[dg[0]] = 'd'
dictionary[dg[1]] = 'g'
else:
dictionary[dg[1]] = 'd'
dictionary[dg[0]] = 'g'
# Parse mixed digits to digits
parsed_number = [parse_digit(dictionary, mixed_digit) for mixed_digit in outputs]
s = parsed_number[0] * 1000 + parsed_number[1] * 100 + parsed_number[2] * 10 + parsed_number[3]
total += s
print(total)
entries = read('input.txt')
solve(entries)