Day 2
Wow, Santa sure likes to travel stylishly. Remind me to buy a toboggan for the next time I want to sled my way to the airport. But of course, the toboggan rental shop is having some trouble too - this time with their corrupted password database.
To try to debug the problem, they have created a list (your puzzle input) of passwords (according to the corrupted database) and the corporate policy when that password was set.
1-3 a: abcde
1-3 b: cdefg
1-3 b: cdefg
First, we do a little bit of string manipulation to extract the necessary information from our given dataset.
import pandas as pd
import numpy as np
# import from given input
df1 = pd.read_csv("input.txt", header=None)
arr=np.ndarray.flatten(df1.values)
df = pd.DataFrame(arr,columns=['password'])
# formatting strings
df[['num','letter','password']] = df['password'].str.split(' ',expand=True)
df[['num1','num2']] = df['num'].str.split('-',expand=True)
df['letter'] = df['letter'].map(lambda x: x.strip(':'))
# as an example, show top 3 formatted entries
df.head(3)
password | num | letter | num1 | num2 | |
---|---|---|---|---|---|
0 | qllllqllklhlvtl | 8-11 | l | 8 | 11 |
1 | wmmmmmttm | 1-3 | m | 1 | 3 |
2 | pgppp | 2-4 | p | 2 | 4 |
Part 1
Their password database seems to be a little corrupted: some of the passwords wouldn’t have been allowed by the Official Toboggan Corporate Policy that was in effect when they were chosen. The password policy indicates the lowest and highest number of times a given letter must appear for the password to be valid. For example, 1-3 a means that the password must contain a at least 1 time and at most 3 times.
Seems pretty simple - we can use the count() method to count the frequency of the letter in the password, and check if its within our desired range.
def isValidPassword_p1(password, num1, num2, letter):
# counting frequency of letter in password
freq=password.count(letter)
# check if letter in specified range
return (freq >= int(num1) and freq <= int(num2))
df['valid_p1']=df.apply(lambda x: isValidPassword_p1(x['password'], x['num1'], x['num2'], x['letter']), axis=1)
df['valid_p1'].value_counts()
False 584
True 416
Name: valid_p1, dtype: int64
Ans: 416
Part 2
The shopkeeper suddenly realizes that he just accidentally explained the password policy rules from his old job at the sled rental place down the street! The Official Toboggan Corporate Policy actually works a little differently. I’m a little worried about the cybersecurity of this toboggan shop ngl.
Alrighty! This one is a bit more of a challenge. I’ll take the opportunity to explain a little bit about logic, and logic gates! In this problem, we want only one of the letters to match with our specified character. Let’s arbitrarily define 2 intputs: whether the left character matches, and whether the right character matches. Placed into a truth table (where 1: True, 0: False), we have:
Left | Right | Output |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
This is a logic gate at its core - specifically, finding the relationship between one or more inputs (Left and Right in our case) and its single output. In our case, this is the equivalent to a XOR gate! There are other logic gates as well, as listed here:
AND
,&
: Sets each bit to 1 if both bits are 1OR
,|
: Sets each bit to 1 if one of two bits is 1XOR
,^
: Sets each bit to 1 if only one of two bits is 1NOT
,~
: Inverts all the bits
Of course, you can also have a combination of these, such as a XNOR
or NAND
gate. In real life applicatins, these logic gates are built using diodes or transistors (a really cool exercise, if you’re ever bored!) that essentially act as electronic switches. Of course, anything can be used to make logic gates, from electromagnetic relays1, mechanical parts2,fluidics3 and even optics4!
Thankfully, in python, the XOR gate is easy enough to find - we simply use the bitwise operator ^
. So, we pass in our two inputs and voila!
def isValidPassword_p2(password, num1, num2, letter):
# function is essentially an XNOR gate!
l1 = (password[int(num1)-1]==letter) # check if 1st character matches
l2 = (password[int(num2)-1]==letter) # check if 2nd character matches
return (l1^l2)
df['valid_p2']=df.apply(lambda x: isValidPassword_p2(x['password'], x['num1'], x['num2'], x['letter']), axis=1)
df['valid_p2'].value_counts()
True 688
False 312
Name: valid_p2, dtype: int64
Ans: 688
Thoughts after day 2: we love pandas! but also, logic ❤️
-
Pott, V. et al. Mechanical Computing Redux: Relays for Integrated Circuit Applications. Proceedings of the IEEE 98, 2076–2094 (2010). ↩
-
Song, Y. et al. Additively manufacturable micro-mechanical logic gates. Nature Communications 10, 882 (2019) ↩
-
Cheow, L. F., Yobas, L. & Kwong, D.-L. Digital microfluidics: Droplet based logic gates. Appl. Phys. Lett. 90, 054107 (2007). ↩
-
Min Zhang, Ling Wang & Peida Ye. All optical XOR logic gates: technologies and experiment demonstrations. IEEE Communications Magazine 43, S19-S24 (2005). ↩