1
- from typing import List
2
1
import string
2
+ from typing import List
3
3
4
4
5
5
class StrongPassswordChecker :
@@ -16,6 +16,9 @@ def _has_digits(self) -> bool:
16
16
return bool (set (self ._password ) & set (string .digits ))
17
17
18
18
def _sequences_longer_than_two (self ) -> List [int ]:
19
+ """
20
+ Return lengths of sequences in the password that have length more than 2
21
+ """
19
22
count = 0
20
23
prev = ""
21
24
@@ -37,39 +40,50 @@ def _sequences_longer_than_two(self) -> List[int]:
37
40
return sequences
38
41
39
42
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 ())
47
49
)
48
- to_modify = longer_than_two
49
50
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
54
57
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 )
56
60
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 ()
59
70
while last > 2 :
60
71
can_delete = last % 3 + 1
61
72
if can_delete <= to_delete :
62
73
to_delete -= can_delete
63
74
last -= can_delete
64
- to_modify -= 1
75
+ to_replace -= 1
65
76
else :
66
77
break
67
78
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
71
85
72
- return max ( to_add , to_modify , to_fix )
86
+ return modifications
73
87
74
88
75
89
class Solution :
0 commit comments