Day 25: Code Chronicle
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Python3
ah well this year ends with a simple ~12.5 ms solve and not too much of a brain teaser. Well at least I got around to solving all of the challenges.
Code
from os.path import dirname,realpath,join from collections.abc import Callable def profiler(method) -> Callable[..., any]: from time import perf_counter_ns def wrapper_method(*args: any, **kwargs: any) -> any: start_time = perf_counter_ns() ret = method(*args, **kwargs) stop_time = perf_counter_ns() - start_time time_len = min(9, ((len(str(stop_time))-1)//3)*3) time_conversion = {9: 'seconds', 6: 'milliseconds', 3: 'microseconds', 0: 'nanoseconds'} print(f"Method {method.__name__} took : {stop_time / (10**time_len)} {time_conversion[time_len]}") return ret return wrapper_method @profiler def solver(locks_and_keys_str: str) -> int: locks_list = [] keys_list = [] for schematic in locks_and_keys_str.split('\n\n'): if schematic[0] == '#': locks_list.append(tuple([column.index('.') for column in zip(*schematic.split())])) else: keys_list.append(tuple([column.index('#') for column in zip(*schematic.split())])) count = 0 for lock_configuration in locks_list: for key_configuration in keys_list: for i,l in enumerate(lock_configuration): if l>key_configuration[i]: # break on the first configuration that is invalid break else: # skipped when loop is broken count += 1 return count if __name__ == "__main__": BASE_DIR = dirname(realpath(__file__)) with open(join(BASE_DIR, r'input'), 'r') as f: input_data = f.read().replace('\r', '').strip() result = solver(input_data) print("Day 25 final solve:", result)
Congrats on reaching the finish line!
The bit that caught me out was that the key + lock should equal 5 in reality, instead of being up to 5 in the challenge.
Thanks! I quickly wrote it but didn’t think to count things. I just took the index of where the edge was located at and ran with it.
So I don’t understand what you mean by equal 5. Could you elaborate? Cause I must have read the challenge text differently.
For a real world lock, the key height + pin height must equal the height of the barrel exactly. If it is taller or shorter, the lock will bind and not open.
https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Pin_tumbler_no_key.svg/400px-Pin_tumbler_no_key.svg.png
For the challenge, as long as its not overlapping (too tall), its a valid key/lock pair.
Oh! I didn’t think it that way, lol, I was thinking this quickly through. I didn’t think of relating to physical locks because it clearly said it was virtual. But I guess, there could theoretically be a physical tumbler lock with 0-5 spacers, it would just be a tall lock. You know like how some master keys have it so that there are spacers for the master key or the client key to open the lock.