-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday4.py
125 lines (95 loc) · 3.58 KB
/
day4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""
--- Day 4: Secure Container ---
You arrive at the Venus fuel depot only to discover it's protected by a
password. The Elves had written the password on a sticky note, but someone
threw it out.
However, they do remember a few key facts about the password:
It is a six-digit number. The value is within the range given in your
puzzle input. Two adjacent digits are the same (like 22 in 122345). Going
from left to right, the digits never decrease; they only ever increase or
stay the same (like 111123 or 135679).
Other than the range rule, the following are true:
111111 meets these criteria (double 11, never decreases). 223450 does not
meet these criteria (decreasing pair of digits 50). 123789 does not meet
these criteria (no double).
How many different passwords within the range given in your puzzle input meet
these criteria?
Your puzzle input is 138307-654504.
--- Part Two ---
An Elf just remembered one more important detail: the two adjacent matching
digits are not part of a larger group of matching digits.
Given this additional criterion, but still ignoring the range rule, the
following are now true:
112233 meets these criteria because the digits never decrease and all
repeated digits are exactly two digits long. 123444 no longer meets the
criteria (the repeated 44 is part of a larger group of 444). 111122 meets
the criteria (even though 1 is repeated more than twice, it still contains
a double 22).
How many different passwords within the range given in your puzzle input meet
all of the criteria?
Your puzzle input is still 138307-654504.
"""
from typing import List
from runner import run
def digit(number, n_digit):
"""Return the nth digit of a given number"""
return number // 10 ** n_digit % 10
def num_passwords1():
"""Return the number of passwords that satisfy the criteria."""
count = 0
for number in range(138307, 654505):
a = digit(number, 5)
b = digit(number, 4)
c = digit(number, 3)
d = digit(number, 2)
e = digit(number, 1)
f = digit(number, 0)
if b < a or c < b or d < c or e < d or f < e:
continue
if a != b != c != d != e != f:
continue
count += 1
return count
def main1():
"""Print the number of passwords."""
print(num_passwords1())
def digits_list(number):
"""Return the digits of the given number as a list."""
return [int(c) for c in str(number)]
def count_occurrences(ns):
"""
Given the list of digits, return a list that for each digits contains a
list of consecutive occurrences.
"""
consecutive_occurrences: List[List[int]] = [
[], [], [], [], [], [], [], [], [], []
]
last_encountered = None
for n in ns:
occurrences = consecutive_occurrences[n]
if last_encountered is None:
occurrences.append(1)
elif last_encountered == n:
occurrences[-1] += 1
else:
occurrences.append(1)
last_encountered = n
return consecutive_occurrences
def num_passwords2():
"""Calculate the number of passwords that satisfy the criteria."""
count = 0
for number in range(138307, 654505):
ns = digits_list(number)
a, b, c, d, e, f = ns
if b < a or c < b or d < c or e < d or f < e:
continue
relevant = [counts for counts in count_occurrences(ns) if 2 in counts]
if not relevant:
continue
count += 1
return count
def main2():
"""Print the number of passwords."""
print(num_passwords2())
if __name__ == '__main__':
run(main1, main2)