Advent-of-Code/2021/8/main2.py

131 lines
4.3 KiB
Python

# IDEAS(dev):
# - You might not have to determine all the positions if the numbers to decode don't use them
# e.g. while(number to decode NOT IN numbers decodable) { do everything }
# -
# NOTES(dev):
# - It looks like the codes are NOT always printed in the same order. For example, if one shows up
# as 'cg', it might also later show up as 'gc' in the same line.
# 0: 1: 2: 3: 4:
# aaaa .... aaaa aaaa ....
# b c . c . c . c b c
# b c . c . c . c b c
# .... .... dddd dddd dddd
# e f . f e . . f . f
# e f . f e . . f . f
# gggg .... gggg gggg ....
# 5: 6: 7: 8: 9:
# aaaa aaaa aaaa aaaa aaaa
# b . b . . c b c b c
# b . b . . c b c b c
# dddd dddd .... dddd dddd
# . f e f . f e f . f
# . f e f . f e f . f
# gggg gggg .... gggg gggg
# initialize shared data:
possibilities = {}
all_possibilities = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ]
# functions:
def ResetData():
possibilities.clear()
for letter in all_possibilities:
possibilities[letter] = list(all_possibilities)
def RemoveImpossibleLetters(good_letters, good_positions):
# generate inverse list of good_positions
bad_positions = list(all_possibilities)
for position in good_positions:
bad_positions.remove(position)
# first, get rid of the other letters from the positions used
for position in good_positions: # positions used
to_remove_list = []
for l in possibilities[position]:
if(not (l in good_letters)):
to_remove_list.append(l)
for to_remove in to_remove_list:
if(to_remove in possibilities[position]):
possibilities[position].remove(to_remove)
# second, get rid of the good letters from all the other positions
for position in bad_positions: # positions not used
for to_remove in good_letters:
if(to_remove in possibilities[position]):
possibilities[position].remove(to_remove)
def ParsePossibilities(text):
text_len = len(text)
# The easy ones first:
if(text_len == 2):
good_letters = list(text)
good_positions = ['c', 'f']
RemoveImpossibleLetters(good_letters, good_positions)
if(text_len == 3):
good_letters = list(text)
good_positions = ['a', 'c', 'f']
RemoveImpossibleLetters(good_letters, good_positions)
if(text_len == 4):
good_letters = list(text)
good_positions = ['b', 'c', 'd', 'f']
RemoveImpossibleLetters(good_letters, good_positions)
# This one straight up doesn't help:
# if(text_len == 7):
# good_letters = list(text)
# good_positions = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
# RemoveImpossibleLetters(good_letters, good_positions)
# The harder ones second:
# if(text_len == 5):
# Could be 2, 3, or 5
# MUST contain positions 'a', 'd', and 'g' in any 5-position number
# MIGHT contain positions 'b' and 'f' for FIVE
# 'c' and 'e' for TWO
# 'c' and 'f' for THREE
# if one of them is found with two others, it's either c or f
# if one of them is not found with two others, it could be b or e
# if(text_len == 6):
# Could be 0, 6, or 9
# MUST contain positions 'a', 'b', 'f', and 'g' in any 6-position number
# MIGHT contain positions 'c' and 'd' for NINE
# 'c' and 'e' for ZERO
# 'd' and 'e' for SIX
total = 0
with open('example_data', 'r') as fp:
# NOTE(dev): We assume all lines are the same length
for line in fp:
ResetData()
split_line = line.split(' | ')
data = split_line[0].split()
# print(data)
codes = split_line[1]
data += codes
for val in codes.split():
if(len(val) in [2, 3, 4, 7]):
total += 1
for text in data:
ParsePossibilities(text.strip())
asdf = possibilities.items()
asdf = list(asdf)
asdf.sort()
print(asdf)
# part 1 answer:
print(total)
# # DEBUG(dev):
# print(possibilities)