Sean McLemon | Advent of Code

Home | Czech | Blog | GitHub | Advent Of Code | Notes


2020-12-25 - Combo Breaker

(original .ipynb)

Day 25 input is two integers representing readings from an RFID handshake (mine is here). Part 1 involves using these digits, a known value (the "subject" - 7) and the description of an algorithm to find out an encryption key. There is no Part 2 :-)

Looking back on Advent of Code I really enjoyed many of the problems. I am glad I completed it on Christmas Day proper, there's a nice sense of satisfaction and accomplishment that comes with that. I don't want to write a whole bunch about this but I'll summarise a few things:

  1. It was really motivating to have a few colleagues working through the puzzles at the same time. Not in a competitive way, but in an encouraging way.
  2. I am beyond impressed at (my colleague) Rob's decision use F#, and as a result feel a bit humbled by my use of Python :-D
  3. A couple of maths ones really messed me up - I feel like I cut corners on them.
  4. Getting up at 6am every day to start (if not exactly finish) my problems was a great idea. Towards the end I didn't manage them before I had to go take my dog Alfie out (usually I gave it 1 hour and a half), but it was really good.
  5. The latter ~7 problems or so were much harder. I rarely take time off just before christmas, but if I have days off next year I'll use them up in the run-up to christmas to ease this a bit (and make xmas prep a bit less stressful at the same time).
  6. I'd like to continue doing little puzzles like this through the year, but at a much reduced pace - once a week or fortnight. I'll maybe revisit Project Euler or the puzzles given out by Interview Cake.

puzzle_input_str = open("puzzle_input/day25.txt", "r").read()

test_input_str = """5764801
17807724"""

# TODO: check why this constant looks like the 27th of December 2020
special_divisor = 20201227

def find_loop_size(subject, public_key):
    loop_size = 0
    calculated_public_key = 1
    
    while public_key != calculated_public_key:
        loop_size += 1
        #calculated_public_key = calculate_key(subject, loop_size)
        calculated_public_key = (calculated_public_key * subject) % special_divisor

    return loop_size

def calculate_key(subject, loop_size):
    public_key = 1
    while loop_size > 0:
        public_key = (public_key * subject) % special_divisor
        loop_size -= 1
        
    return public_key
    
def part1(input_str):
    # don't think we know who is who, but for the sake of naming them
    my_pub_key, door_pub_key = [int(key_str) for key_str in input_str.split("\n")]
    
    # is this always 7?
    my_loop_size = find_loop_size(7, my_pub_key)
    door_loop_size = find_loop_size(7, door_pub_key)
    
    print(my_pub_key, door_pub_key)
    print(my_loop_size, door_loop_size)
    
    print(pow(my_pub_key, door_loop_size, special_divisor), pow(door_pub_key, my_loop_size, special_divisor))
    
# expected result from test_input_str: 14897079
#part1(test_input_str)
part1(puzzle_input_str)
12092626 4707356
14775052 12413864
18329280 18329280