143 lines
No EOL
4 KiB
Python
143 lines
No EOL
4 KiB
Python
def AOC_8_a():
|
|
with open("src/input8.txt") as file:
|
|
lines = file.read().splitlines()
|
|
lines = [x.split(" | ")[1].split(' ') for x in lines]
|
|
total = 0
|
|
for line in lines:
|
|
for item in line:
|
|
if len(item) == 2 or len(item) == 3 or len(item) == 4 or len(item) == 7:
|
|
total += 1
|
|
print(total)
|
|
|
|
|
|
def AOC_8_b():
|
|
with open("input.txt") as file:
|
|
lines = file.read().splitlines()
|
|
lines = [x.split(" | ") for x in lines]
|
|
total = 0
|
|
for (lefthand, righthand) in lines:
|
|
lefts = lefthand.split(' ')
|
|
digits = fill_dict(lefts)
|
|
digits["2"] = find_two(digits["1"], digits["len5"] + digits["len6"])
|
|
digits["9"] = find_nine(digits["4"], digits["len6"])
|
|
|
|
digits["len6"].remove(digits["9"])
|
|
|
|
digits["5"] = find_five(digits["2"], digits["len5"])
|
|
|
|
digits["len5"].remove(digits["2"])
|
|
digits["len5"].remove(digits["5"])
|
|
|
|
digits["3"] = find_three(digits["len5"])
|
|
digits["6"] = find_six(digits["5"], digits["len6"])
|
|
|
|
digits["len6"].remove(digits["6"])
|
|
|
|
digits["0"] = find_zero(digits["len6"])
|
|
|
|
del digits["len5"]
|
|
del digits["len6"]
|
|
|
|
number = ""
|
|
for item in righthand.split(' '):
|
|
item = "".join(sorted(item))
|
|
for key, value in digits.items():
|
|
if (value == item):
|
|
number += key
|
|
print(number)
|
|
total += int(number)
|
|
print(total)
|
|
|
|
|
|
def pd(dict):
|
|
for (key, value) in dict.items():
|
|
print(key, ": ", value)
|
|
|
|
|
|
# 0 is the last number to find, and is just the last remaining not used string
|
|
def find_zero(candidates):
|
|
return candidates[0]
|
|
|
|
|
|
# 2 is the only digit that shares a unique single segment with 1 (5 and 6 also share
|
|
# a single segment with 1, but they're thus not unique) among unknown digits. We need both len5 and len6
|
|
# to check for this uniqueness.
|
|
def find_two(segment, candidates):
|
|
az = {x: shares_only_one_segment(x, segment) for x in candidates if shares_only_one_segment(x, segment) is not None}
|
|
return least_frequent(az)
|
|
|
|
|
|
# 3 will be the only len5 segment not assigned at this point
|
|
def find_three(candidates):
|
|
return candidates[0]
|
|
|
|
|
|
# 5 is the only digit that shares three segments with 2
|
|
def find_five(segment, candidates):
|
|
for can in candidates:
|
|
if (shares_x_segments(segment, can, 3)):
|
|
return can
|
|
|
|
|
|
# 6 is the only digit that shares five segments with 5
|
|
def find_six(segment, candidates):
|
|
for can in candidates:
|
|
if (shares_x_segments(segment, can, 5)):
|
|
return can
|
|
|
|
|
|
# 9 is the only digit that shares four segments with 4
|
|
def find_nine(segment, candidates):
|
|
for can in candidates:
|
|
if (shares_x_segments(segment, can, 4)):
|
|
return can
|
|
|
|
|
|
def least_frequent(dict):
|
|
list = [value for (key, value) in dict.items()]
|
|
lowest_value = min(set(list), key=list.count)
|
|
|
|
for key, value in dict.items():
|
|
if (lowest_value == value):
|
|
return key
|
|
|
|
|
|
def shares_only_one_segment(segment, candidate):
|
|
total = 0
|
|
for a in segment:
|
|
for b in candidate:
|
|
if (a == b):
|
|
total += 1
|
|
shared = a
|
|
return shared if total == 1 else None
|
|
|
|
|
|
def shares_x_segments(segment, candidate, x):
|
|
total = 0
|
|
for seg in segment:
|
|
for can in candidate:
|
|
if (seg == can):
|
|
total += 1
|
|
return total == x
|
|
|
|
|
|
def fill_dict(lefts):
|
|
digits = {"len5": [], "len6": []}
|
|
for num in lefts:
|
|
num = "".join(sorted(num))
|
|
if (len(num) == 2):
|
|
digits["1"] = num
|
|
if (len(num) == 4):
|
|
digits["4"] = num
|
|
if (len(num) == 3):
|
|
digits["7"] = num
|
|
if (len(num) == 7):
|
|
digits["8"] = num
|
|
if (len(num) == 5):
|
|
digits["len5"].append(num)
|
|
if (len(num) == 6):
|
|
digits["len6"].append(num)
|
|
return digits
|
|
|
|
if __name__ == '__main__':
|
|
AOC_8_b() |