Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from collections import Counter, defaultdict
- from enum import IntEnum
- raw = [line.split(' | ') for line in f_input.split('\n')]
- all_unique, outputs = zip(*raw)
- all_unique = [un.split() for un in all_unique]
- outputs = [output.split() for output in outputs]
- flat_outputs = [item for sublist in outputs for item in sublist]
- output_counter = Counter(len(fo) for fo in flat_outputs)
- print(sum([count for segments, count in output_counter.items() if segments in (2, 3, 4, 7)]))
- # part 2
- class D(IntEnum):
- '''
- 000
- 1 2
- 1 2
- 333
- 4 5
- 4 5
- 666
- '''
- TOP = 0
- TOPLEFT = 1
- TOPRIGHT = 2
- MIDDLE = 3
- BOTTOMLEFT = 4
- BOTTOMRIGHT = 5
- BOTTOM = 6
- ENCODER = {(D.TOP, D.TOPLEFT, D.TOPRIGHT, D.BOTTOMLEFT, D.BOTTOMRIGHT, D.BOTTOM): '0',
- (D.TOPRIGHT, D.BOTTOMRIGHT): '1',
- (D.TOP, D.TOPRIGHT, D.MIDDLE, D.BOTTOMLEFT, D.BOTTOM): '2',
- (D.TOP, D.TOPRIGHT, D.MIDDLE, D.BOTTOMRIGHT, D.BOTTOM): '3',
- (D.TOPLEFT, D.TOPRIGHT, D.MIDDLE, D.BOTTOMRIGHT): '4',
- (D.TOP, D.TOPLEFT, D.MIDDLE, D.BOTTOMRIGHT, D.BOTTOM): '5',
- (D.TOP, D.TOPLEFT, D.MIDDLE, D.BOTTOMLEFT, D.BOTTOMRIGHT, D.BOTTOM): '6',
- (D.TOP, D.TOPRIGHT, D.BOTTOMRIGHT): '7',
- (D.TOP, D.TOPLEFT, D.TOPRIGHT, D.MIDDLE, D.BOTTOMLEFT, D.BOTTOMRIGHT, D.BOTTOM): '8',
- (D.TOP, D.TOPLEFT, D.TOPRIGHT, D.MIDDLE, D.BOTTOMRIGHT, D.BOTTOM): '9',
- }
- def encode_segments(segments, mapping):
- '''mapping = {'a': D.TOPRIGHT, 'b': D.BOTTOMRIGHT, 'c': D.BOTTOM, 'd': D.TOP,
- 'e': D.TOPLEFT, 'f': D.MIDDLE, 'g': D.BOTTOMLEFT}
- encode_segments('acedgfb', mapping) => '8'
- '''
- encodable = tuple(sorted(mapping[letter] for letter in segments))
- return ENCODER[encodable]
- def decode_segments(unique_specification):
- '''['acedgfb', 'cdfbe', 'gcdfa', 'fbcad', 'dab', 'cefabd', 'cdfgeb', 'eafb', 'cagedb', 'ab']
- => {'a': D.TOPRIGHT, 'b': D.BOTTOMRIGHT, 'c': D.BOTTOM, 'd': D.TOP,
- 'e': D.TOPLEFT, 'f': D.MIDDLE, 'g': D.BOTTOMLEFT}'''
- def create_length_dictionary(unique_specification):
- '''u_s = ['acedgfb', 'cdfbe', 'gcdfa', 'fbcad', 'dab', 'cefabd', 'cdfgeb', 'eafb', 'cagedb', 'ab']
- create_length_dictionary(u_s) => {2: ['ab'], 3: ['dab']: 4: ['eafb'], 5: ['cdfbe', 'gcdfa', 'fbcad],
- 6: ['cefabd', 'cdfgeb', 'cagedb'], 7: ['acedgfb']}
- '''
- ldict = defaultdict(list)
- for letters in unique_specification:
- ldict[len(letters)].append(letters)
- return ldict
- mapping = dict()
- ldict = create_length_dictionary(unique_specification)
- # we know these
- the_one, the_seven = set(*ldict[2]), set(*ldict[3])
- the_four, the_eight = set(*ldict[4]), set(*ldict[7])
- # 3 segments (the seven) minus 2 (the one) segments yields D.TOP segment
- (segment,) = the_seven - the_one
- mapping[segment] = D.TOP
- # 4 segments (the four) minus 3 (the seven) segments yields D.TOPLEFT and D.MIDDLE
- TL_M = the_four - the_seven
- # 7 segments (the eight) minus each of the three 6 segment configurations yields 1 segment each
- three_1_seg = [the_eight - set(six) for six in ldict[6]]
- assert all(len(seg) == 1 for seg in three_1_seg)
- # we can decouple D.TOPLEFT and D.MIDDLE by checking each of the leftovers
- # the one with an overlap is D.MIDDLE, the other is D.TOPLEFT
- for segment in three_1_seg:
- if TL_M & segment:
- (tl_seg,) = TL_M - segment
- mapping[tl_seg] = D.TOPLEFT
- (segment,) = segment
- mapping[segment] = D.MIDDLE
- # we now know D.TOP, D.TOPLEFT amd D.MIDDLE
- # from the 5 segment results (digits 2, 3 and 5) and the digit 1, we can unlock much
- # first, the one with BOTH segments in digit 1 is the three, and the unknown
- # segment is D.BOTTOM
- for segments in ldict[5]:
- r_unk = set(segments) - the_one
- if len(r_unk) == 3:
- (segment,) = r_unk - set(mapping.keys())
- mapping[segment] = D.BOTTOM
- #the_three = segments
- # now if we subtract our knowns (D.TOP, D.TOPLEFT, D.MIDDLE, D.BOTTOM) from the 5 segment results, the one that isn't
- # two results will yield the bottom right
- knowns = set(mapping.keys())
- for segments in ldict[5]:
- remain = set(segments) - knowns
- if len(remain) == 1:
- (segment,) = remain
- mapping[segment] = D.BOTTOMRIGHT
- # two left, D.TOPRIGHT and D.BOTTOMLEFT. top right is easy, knowns shared with the one
- (segment,) = the_one - set(mapping.keys())
- mapping[segment] = D.TOPRIGHT
- (segment,) = set('abcdefg') - set(mapping.keys())
- mapping[segment] = D.BOTTOMLEFT
- assert len(mapping) == 7
- return mapping
- # okay, let's do this.
- final_answer = 0
- for all_u, output in zip(all_unique, outputs):
- mapping = decode_segments(all_u)
- final_answer += int(''.join([encode_segments(sequence, mapping) for sequence in output]))
- print(final_answer)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement