0

I am trying to build a strong password checker using Python. The conditions of the password are as follows:

  • It has at least 6 characters and at most 20 characters.
  • It must contain at least one lowercase letter, at least one uppercase letter, and at least one digit.
  • It must NOT contain three repeating characters in a row ("...aaa..." is weak, but "...aa...a..." is strong, assuming other conditions are met).

Write a function strongPasswordChecker(s), that takes a string s as input, and return the MINIMUM change required to make s a strong password. If s is already strong, return 0.

Insertion, deletion or replace of any one character are all considered as one change.

The following is my attempt:

import re

class Solution:
    def strongPasswordChecker(self, s: str) -> int:

        # Holds the change
        change = 0

        # Checks if the password length is less than 6
        if len(s) < 6:
            change += 6 - len(s)

        # Checks if the password length is greater than 20
        elif len(s) > 20:
            change += len(s) - 20

        # Checks if the password has at least one digit
        elif re.search(r'\d', s):
            change += 1

        # Checks if the password has at least one upper case letter
        elif re.search(r'[A-Z]', s):
            change += 1

        # Checks if the password has at least one lower case letter
        elif re.search(r'[a-z]', password):
            change += 1

        # Checks for repeating characters
        for i in range(1, len(s)):
            if i >= 3 and i < len(s):
                if s[i] == s[i + 1] and s[i + 1] == s[i + 2]:
                    change += 1

        return change

Despite checking for the repeating characters with the if statement above, I'm still getting the following error:

IndexError: String Index out of range

1
  • On a separate issue: shouldn't all your regex expressions have not infront. For instance shouldn't elif re.search(r'\d', s): be elif not re.search(r'\d', s):? Commented Jan 7, 2020 at 16:20

1 Answer 1

4

The problem is this statement can go out of bounds potentially, for example when i == len(s) - 1 then s[i + 1] and s[i + 2] will both index out of bounds.

for i in range(1, len(s)):
    if i >= 3 and i < len(s):
        if s[i] == s[i + 1] and s[i + 1] == s[i + 2]:
            change += 1

If you want to make sure you don't have groups of 3 or longer, I'd use itertools.groupby

>>> any(len(list(g)) > 2 for k, g in groupby('aabbcc'))
False
>>> any(len(list(g)) > 2 for k, g in groupby('aabbbbbcc'))
True

To replace your for loop in your code, you'd use this like

elif any(len(list(g)) > 2 for k, g in groupby(s)):
    change += 1
Sign up to request clarification or add additional context in comments.

4 Comments

Doesn't your code just check only for aabbcc and aabbbbbcc?
Obviously that was just an example, you should pass the string s in your case
How do I use this in an if statement?
@OnurOzbek See the edit on the bottom of my answer, you can use this expression as another elif case

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.