Home > Blockchain >  How can I make the output return False if a character in the string appears three times in a row?
How can I make the output return False if a character in the string appears three times in a row?

Time:11-23

So I created this code that takes in a list and returns True or False depending on whether they meet these criterias or not. Here is my code

def passwordlength(password: str):
    upper = digit = special = False
    for char in password:
        if char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" :
            upper = True
        elif char in "1234567890":
            digit = True
        elif char in "$#@%!":
            special = True
    return upper and digit and special

def passwordOK(password: str):
    if passwordlength(password):
        if not (6 < len(password) < 12):
            return False
        else:
            return True
    return False

Now I want to add a new twist, which is that if any letter, number, character in the list appears 3 times in a row, the result will return False.. here is my attempt at it...

    def passwordlength(password: str):
    upper = digit = special = False
    for char in password:
        if char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" :
            upper = True
        elif char in "1234567890":
            digit = True
        elif char in "$#@%!":
            special = True
    return upper and digit and special

def passwordOK(password: str):
    if passwordlength(password):
        if not (6 < len(password) < 12):
            return False
        for char in password:
            if password.count(char) > 3:
                return False
        return True
    return False

However, this clearly doesn't work at all.. what am I doing wrong here?? what should my code be in order for my output to be correct??

CodePudding user response:

Use groupby from itertools. With this version, you set the number of characters in a row.

from itertools import groupby

def passwordinarow(password: str, n: int=3):
    """Return True if password contains 'n' characters in a row else False."""
    return any([len(list(g)) >= n for c, g in groupby(password)])

Test:

>>> passwordinarow('AAABC123$')
True

>>> passwordinarow('ABC123$')
False

CodePudding user response:

If you want to return false when a character, number appears 3 times in the string, clearly you should change your if condition like this:

[...]
for char in password:
    if password.count(char) == 3:
        return False
[...]

If you meant at least 3 times appearance:

[...]
for char in password:
    if password.count(char) >= 3:
        return False
[...]

However password.count(char) will loop over the whole password for each char, so why don't we loop once, and get the result:

[...]
from collections import defaultdict
defdict = defaultdict(lambda: 0)
for char in password:
    defdict[char]  = 1
    if defdict[char] >= 3:
        return false
[...]

Update:

according to your comment:

I mean like 3 times in a row btw, like if its AAA, BBB, CCC then it should return false.. if it's ABANA.. then it doesn't matter

Define a function like this:

def has_3consecutive_char(password: str) -> bool:
    from collections import defaultdict
    defdict = defaultdict(lambda: 0)
    prev_char = ""
    for char in password:
        if prev_char == char:
            defdict[char]  = 1
            if defdict[char] >= 2:
                return True
        else:
            defdict[char] = 0
        prev_char = char
    return False

Then use it in your passwordOK function:

def passwordOK(password: str):
    if passwordlength(password):
        if not (6 < len(password) < 12):
            return False
        if has_3consecutive_char(password):
                return False
        return True
    return False

CodePudding user response:

There are many different ways to approach this.

Personally I might do something like:

def has_repeated_chars(password: str, n_repetitions: int=3) -> bool:
    ngrams = zip(*(password[i] for i in range(n_repetitions)))
    return min(len(set(trigram)) for trigram in ngrams) == 1

Generally the logic is to create an iterable of ngrams of length 3, create a set for each ngram and if the set is of length 1 then we know the same character has been repeated 3 times.

  • Related