summaryrefslogtreecommitdiffstats
path: root/11/solution.py
diff options
context:
space:
mode:
Diffstat (limited to '11/solution.py')
-rw-r--r--11/solution.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/11/solution.py b/11/solution.py
new file mode 100644
index 0000000..5c044b3
--- /dev/null
+++ b/11/solution.py
@@ -0,0 +1,69 @@
+"""Advent of code 2015 day 11"""
+
+def next_password(password: str) -> str:
+ """Increment the password
+ "a" -> "b"
+ "az" -> "ba"
+ """
+ if password[-1] == 'z':
+ return next_password(password[:-1]) + 'a'
+ else:
+ return password[:-1] + chr(ord(password[-1]) + 1)
+
+def has_straight(password: str) -> bool:
+ """Check if a password contains a sequence of at least three consecutive characters"""
+ for i in range(len(password) - 2):
+ if ord(password[i]) + 1 == ord(password[i+1]) and ord(password[i+1]) + 1 == ord(password[i+2]):
+ return True
+ return False
+
+def has_pair(password: str) -> bool:
+ """Check if a password contains at least one pair of letters"""
+ for i in range(len(password) - 1):
+ if password[i] == password[i+1]:
+ return True
+ return False
+
+def has_pairs(password: str) -> bool:
+ """Check if a password contains at least two different, non-overlapping pairs of letters"""
+ for i in range(len(password) - 1):
+ if password[i] == password[i+1]:
+ return has_pair(password[i+2:])
+ return False
+
+def is_valid(password: str) -> bool:
+ """Check if password is valid
+ Password must:
+ - include one increasing straight of at least three letters
+ - may not contain i, o or l
+ - must contain at least two different, non-overlapping pairs of letters
+ "hijklmmn" -> False
+ "abbceffg" -> True
+ "abbcegjk" -> False
+ """
+ if not has_straight(password):
+ return False
+ if not has_pairs(password):
+ return False
+ if 'i' in password or 'o' in password or 'l' in password:
+ return False
+ return True
+
+def part1(password: str) -> str:
+ """Find the next valid password"""
+ password = next_password(password)
+ while not is_valid(password):
+ password = next_password(password)
+ return password
+
+def part2(password: str) -> str:
+ """Find the next valid password"""
+ password = next_password(part1(password))
+ while not is_valid(password):
+ password = next_password(password)
+ return password
+
+if __name__ == '__main__':
+ inp = 'cqjxjnds'
+ print(part1(inp))
+ print(part2(inp))