A password is considered strong if the below conditions are all met:
- It has at least
6
characters and at most 20
characters.
- It contains at least one lowercase letter, at least one uppercase letter, and at least one digit.
- It does not contain three repeating characters in a row (i.e.,
"...aaa..."
is weak, but "...aa...a..."
is strong, assuming other conditions are met).
Given a string password
, return the minimum number of steps required to make password
strong. if password
is already strong, return 0
.
In one step, you can:
- Insert one character to password,
- Delete one character from password, or
- Replace one character of password with another character.
Example 1:
Input: password = "a"
Output: 5
Example 2:
Input: password = "aA1"
Output: 3
Example 3:
Input: password = "1337C0d3"
Output: 0
Constraints:
1 <= password.length <= 50
password
consists of letters, digits, dot '.'
or exclamation mark '!'
.
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
|
class Solution:
type_sets = [
set('abcdefghijklmnopqrstuvwxyz'),
set('ABCDEFGHIJKLMNOPQRSTUFVWXYZ'),
set('0123456789'),
]
def strongPasswordChecker(self, password: str) -> int:
chars = set(password)
# Check rule 1
num_req_inserts = max(0, 6 - len(password))
num_req_deletes = max(0, len(password) - 20)
# Check rule 2
num_req_types = 0
for t in self.type_sets:
num_req_types += 0 if (chars & t) else 1
# Check rule 3
groups = [len(list(grp)) for _, grp in itertools.groupby(password)]
for _ in range(num_req_deletes):
# Apply best delete
idx, _ = min(
enumerate(groups),
# Ignore groups of length < 3
# 5 - it[1] > 2 when it[1] < 3
key=lambda it: it[1] % 3 if it[1] >= 3 else 5,
)
groups[idx] -= 1
num_req_group_replaces = sum(
group // 3
for group in groups
)
return (
num_req_deletes
+ max(
num_req_types,
num_req_group_replaces,
num_req_inserts,
)
)
|