Skip to content

Commit 068df50

Browse files
committed
1 parent 22fbd84 commit 068df50

File tree

1 file changed

+35
-21
lines changed

1 file changed

+35
-21
lines changed

l33tcode/strong-password-checker.py

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from typing import List
21
import string
2+
from typing import List
33

44

55
class StrongPassswordChecker:
@@ -16,6 +16,9 @@ def _has_digits(self) -> bool:
1616
return bool(set(self._password) & set(string.digits))
1717

1818
def _sequences_longer_than_two(self) -> List[int]:
19+
"""
20+
Return lengths of sequences in the password that have length more than 2
21+
"""
1922
count = 0
2023
prev = ""
2124

@@ -37,39 +40,50 @@ def _sequences_longer_than_two(self) -> List[int]:
3740
return sequences
3841

3942
def to_valid(self) -> int:
40-
to_fix = 0
41-
to_fix += int(not self._has_lowercase())
42-
to_fix += int(not self._has_uppercase())
43-
to_fix += int(not self._has_digits())
44-
45-
longer_than_two = sum(
46-
map(lambda x: x // 3, self._sequences_longer_than_two())
43+
# Amendments we should to to make sure all required types of characters
44+
# are present in the string
45+
to_amend = (
46+
int(not self._has_lowercase())
47+
+ int(not self._has_uppercase())
48+
+ int(not self._has_digits())
4749
)
48-
to_modify = longer_than_two
4950

50-
if 6 <= len(self._password) < 20:
51-
return max(to_modify, to_fix)
52-
elif len(self._password) > 20:
53-
to_delete = len(self._password) - 20
51+
# Replacements we should do in order to break all the sequences having
52+
# length greater than 2
53+
longer_than_two = self._sequences_longer_than_two()
54+
to_replace = sum(map(lambda x: x // 3, longer_than_two))
55+
56+
modifications = 0
5457

55-
longer_than_two_arr = self._sequences_longer_than_two()
58+
if len(self._password) <= 20:
59+
to_add = max(6 - len(self._password), 0)
5660

57-
while to_delete > 0 and longer_than_two_arr:
58-
last = longer_than_two_arr.pop()
61+
modifications = max(to_replace, to_amend, to_add)
62+
else:
63+
to_delete = len(self._password) - 20
64+
65+
# Greedy way to use deletions instead of replacements
66+
# because there is a chance we can save some replacements
67+
# this way and hence get less modificaions
68+
while to_delete > 0 and longer_than_two:
69+
last = longer_than_two.pop()
5970
while last > 2:
6071
can_delete = last % 3 + 1
6172
if can_delete <= to_delete:
6273
to_delete -= can_delete
6374
last -= can_delete
64-
to_modify -= 1
75+
to_replace -= 1
6576
else:
6677
break
6778

68-
return max(to_fix, to_modify) + len(self._password) - 20
69-
else:
70-
to_add = 6 - len(self._password)
79+
# Restore to_delete, since we're making deletions no matter what.
80+
# But we probably reduced the number of replacements on the previous
81+
# step
82+
to_delete = len(self._password) - 20
83+
84+
modifications = max(to_replace, to_amend) + to_delete
7185

72-
return max(to_add, to_modify, to_fix)
86+
return modifications
7387

7488

7589
class Solution:

0 commit comments

Comments
 (0)