56 lines
1.6 KiB
Python
56 lines
1.6 KiB
Python
import re
|
|
import sys
|
|
from collections import Counter
|
|
|
|
|
|
def get_valid_rooms(pinput):
|
|
def only_valid_rooms(l):
|
|
code, id, checksum = re.match(r'^(\D+)(\d+)\[(\D+?)\]$', l.translate({ord('-'): None})).groups()
|
|
mc = Counter(code).most_common()
|
|
mc_sorted = sorted(mc, key=lambda e: (-e[1], e[0])) # because FU, Counter default sort ...
|
|
return ''.join(map(lambda x: x[0], mc_sorted)).startswith(checksum)
|
|
|
|
return filter(only_valid_rooms, pinput.splitlines())
|
|
|
|
|
|
def sum_sector_ids(puzzle):
|
|
return sum(map(int, map(lambda l: re.match(r'.+-(\d+)\[', l).group(1),
|
|
get_valid_rooms(puzzle))))
|
|
|
|
|
|
def decrypt_name(ciphered, id):
|
|
v = ''
|
|
for c in ciphered:
|
|
dec = ord(c) + (id % 26)
|
|
if dec > 122:
|
|
dec -= 26
|
|
v += ' ' if c == '-' else chr(dec)
|
|
return v
|
|
|
|
|
|
def find_np_room(pinput):
|
|
rooms = get_valid_rooms(pinput)
|
|
for r in rooms:
|
|
code, sid = re.match(r'^(\D+)-(\d+)\[', r).groups()
|
|
decrypted = decrypt_name(code, int(sid))
|
|
if decrypted == 'northpole object storage':
|
|
return sid
|
|
|
|
|
|
def run(pinput):
|
|
"""Day 4: Security Through Obscurity"""
|
|
s = sum_sector_ids(pinput)
|
|
np = find_np_room(pinput)
|
|
|
|
print('Sum of sector IDs, real rooms: %s' % s)
|
|
print('Section ID for North Pole storage: %s' % np)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
with open(sys.argv[1], 'r') as f:
|
|
run(f.read())
|
|
except IOError:
|
|
print('please provide a file path to puzzle file, example: ./puzzle.txt')
|
|
except IndexError:
|
|
print('please provide a file path to puzzle file, example: ./puzzle.txt')
|