Strong password checker in Python This is a Leetcode problem - 


  A password is considered strong if below conditions are all met -
  
  1. It has at least 6 characters and at most 20 characters.
  
  2. It must contain at least one lowercase letter, at least one uppercase letter, and at least one digit.
  
  3. 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 strong_password_checker(s), that takes a string s
  as input, and returns the MINIMUM change required to make s a
  strong password. If s is already strong, return 0.
  
  Insertion, deletion or replacements of any one character are all
  considered as one change.


Here is my solution to this challenge - 


def strong_password_checker(s: str) -&gt; int:
    def has_lower(s):
        for c in s:
            if c.islower(): return 1
        return 0

    def has_upper(s):
        for c in s:
            if c.isupper(): return 1
        return 0

    def has_digits(s):
        for c in s:
            if c.isnumeric(): return 1
        return 0

    def find_repeats(s):
        i = 0
        j = 0
        repeats = []
        while i &lt; len(s) - 1:
            if s[i+1] == s[i]:
                i += 1
                continue
            if (i - j + 1) &gt; 2: repeats.append(i - j + 1)
            i += 1
            j = i
        if (i - j + 1) &gt; 2: repeats.append(i - j + 1)
        return repeats

    def repeats_after_delete(reps, d):
        if d &gt;= sum([r - 2 for r in reps]):
            return []
        reps = sorted(reps, key=lambda d: d%3)
        while d &gt; 0:
            for i in range(len(reps)):
                if reps[i] &lt; 3:
                    continue
                r = reps[i] % 3 + 1
                reps[i] -= min(r, d)
                d -= r
                if d &lt;= 0:
                    break
        return [r for r in reps if r &gt; 2]

    def num_repeats_change(repeats):
        return sum([r // 3 for r in repeats])

    total_changes = 0
    format_changes = (1 - has_lower(s)) + (1 - has_upper(s)) + (1 - has_digits(s))
    repeats = find_repeats(s)
    if len(s) &lt; 6:
        repeat_change = num_repeats_change(repeats)
        total_changes = max([6 - len(s), format_changes, repeat_change])
    elif len(s) &gt; 20:
        repeats = repeats_after_delete(repeats, len(s) - 20)
        repeat_change = num_repeats_change(repeats)
        total_changes = len(s) - 20 + max([repeat_change, format_changes])
    else: 
        repeat_change = num_repeats_change(repeats)
        total_changes = max([repeat_change, format_changes])
    return total_changes



Here are some example outputs - 

#print(strongPasswordChecker("aaaaaaaaaaaaAsaxqwd1aaa"))

&gt;&gt;&gt; 6

#Explanation - aa1aa1aa1aAsaxqwd1aa (just an example - delete three characters, add three digits to replace consecutive a's)




#print(strongPasswordChecker("aaaaa"))

&gt;&gt;&gt; 2

#Explanation - aaAaa1 (just an example - add a character (so the length is at least 6), add an uppercase letter to replace consecutive a's)




#print(strongPasswordChecker("aAsaxqwd2aa"))

&gt;&gt;&gt; 0

#Explanation - A strong password (all conditions are met)




Here are the times taken for each output - 

%timeit strongPasswordChecker("aaaaaaaaaaaaAsaxqwd1aaa")
&gt;&gt;&gt; 18.7 µs ± 1.75 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit strongPasswordChecker("aaaaa")
&gt;&gt;&gt; 5.05 µs ± 594 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit strongPasswordChecker("aAsaxqwd2aa")
&gt;&gt;&gt; 7.19 µs ± 469 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)


So, I would like to know whether I could make this program shorter and more efficient.

Any help would be highly appreciated.
You could use this code for checking whether it has an uppercase/lowercase:

if s.lower() == s:
    # doesn't have any uppercase
if s.upper() == s:
    # doesn't have any lowercase


This way, you don't have to iterate through the entire string.