Skip to content

Instantly share code, notes, and snippets.

@markjenkins markjenkins/d4p1.py
Last active Dec 12, 2016

Embed
What would you like to do?
#!/usr/bin/env python3
# Solution to http://adventofcode.com/2016/day/4 part 1
# Mark Jenkins <mark@markjenkins.ca>
from sys import stdin
from collections import Counter
from itertools import islice
CHECKSUM_SIZE = 5
def parse_room(line):
parts = line.split("-")
sector_id_and_checksum = parts[-1].split("[")
return (
''.join(c for c in parts[:-1] if c!="-"), # name letters without "-"
int(sector_id_and_checksum[0]), # sector id
sector_id_and_checksum[1][0:CHECKSUM_SIZE] # checksum
)
def checksum(name):
counts = Counter(name)
# make a sorted iterable of the counts and letters,
# use reverse=True to get the counts in descending order
#
# to take full advantage of sorted, we reverse the ordering of the
# alphabet by converting to integer and subtracting from 'z'
# so that the use of reverse=True doesn't give us z-a, but instead a-z
sorted_count_let_num = sorted(
( (count, ord('z') - ord(let) )
for let, count in counts.items()),
reverse=True)
# construct a string using the first CHECKSUM_SIZE entries
return ''.join(
chr(ord('z') - da_let) # fix the letter reversing and convert back
for da_count, da_let in islice(sorted_count_let_num,
0, CHECKSUM_SIZE) # islice
) # join
def valid_room(name, checksum_in):
return checksum(name)==checksum_in
print( sum( sector_id
for name, sector_id, checksum in (parse_room(line)
for line in stdin )
if valid_room(name, checksum)
) # sum
) # print
#!/usr/bin/env python3
# Solution to http://adventofcode.com/2016/day/4 part 2
# Mark Jenkins <mark@markjenkins.ca>
from sys import stdin
from collections import Counter
from itertools import islice
CHECKSUM_SIZE = 5
def parse_room(line):
parts = line.split("-")
sector_id_and_checksum = parts[-1].split("[")
return (
parts[:-1], # name in parts
int(sector_id_and_checksum[0]), # sector id
sector_id_and_checksum[1][0:CHECKSUM_SIZE] # checksum
)
def checksum(name):
counts = Counter(name)
# make a sorted iterable of the counts and letters,
# use reverse=True to get the counts in descending order
#
# to take full advantage of sorted, we reverse the ordering of the
# alphabet by converting to integer and subtracting 'z'
# so that the use of reverse=True doesn't give us z-a, but instead a-z
sorted_count_let_num = sorted(
( (count, ord('z') - ord(let) )
for let, count in counts.items()),
reverse=True)
# construct a string using the first CHECKSUM_SIZE entries
return ''.join(
chr(ord('z') - da_let) # fix the letter reversing and convert back
for da_count, da_let in islice(sorted_count_let_num,
0, CHECKSUM_SIZE) # islice
) # join
def valid_room(name, checksum_in):
return checksum(''.join(name)) ==checksum_in
def decrypt_letter(c, key):
return chr(
( (ord(c) - ord('a') + key) % 26 ) +
ord('a')
) # chr
def decrypt_room(name, sector_id):
return ' '.join( ''.join( decrypt_letter(c, sector_id) for c in name_part )
for name_part in name )
print( '\n'.join( "%s %s" % (decrypt_room(name, sector_id), sector_id)
for name, sector_id, checksum in (parse_room(line)
for line in stdin )
if valid_room(name, checksum)
) # join
) # print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.