Home > Blockchain >  after u see a valid number, no letter can come after it. how can i solve this?
after u see a valid number, no letter can come after it. how can i solve this?

Time:01-07

“All vanity plates must start with at least two letters.”

“… vanity plates may contain a maximum of 6 characters (letters or numbers) and a minimum of 2 characters.”

“Numbers cannot be used in the middle of a plate; they must come at the end. For example, AAA222 would be an acceptable … vanity plate; AAA22A would not be acceptable. The first number used cannot be a ‘0’.”

“No periods, spaces, or punctuation marks are allowed.”

I solved ever problem but i am having a difficult time solving the highlighted problem. AAA22A or AAA2A as invalid.

def is_valid(s):
    # checks for at least 2 chars and a max of 6 characters
    # and checks for at least 2 uppercase letters
    if len(s) < 2 or len(s) > 6 and s[0:2].isalpha():
        return False

    # checks for periods, spaces, or punctuation marks
    for i in s:
        if i in [".", " ", "!", "?"]:
            return False

    # checks if numbers in string starts with 0
    i = 0
    while i < len(s):
        if s[i].isalpha() == False:
            if s[i] == "0":
                return False
            else:
                break
        i  = 1

    # after u see a valid number, no letter can come after it 
    # this is where the challenge is ,
    for i in s[::-1]:
        if s[i].isalpha() == True:
            for j in s[::-2]:
                if s[j].isalpha == False:
                    return False
                else:
                    break
        else:
            break
    # returns true if all the requirements are passed
    return True

"""i tried to iterate in reverse order but that deems unsuccessful. Not sure how to solve. need help please."""

CodePudding user response:

You can have a function to know if a letter comes after a number or use this piece of code directly:

def letter_after_number(s):
    for i in range(len(s) - 1):
        if s[i].isdigit() and s[i   1].isalpha():
            return False
    return True

here the entire code:

def is_valid(s):
    # checks for at least 2 chars and a max of 6 characters
    # and checks for at least 2 uppercase letters
    if len(s) < 2 or len(s) > 6 and s[0:2].isalpha():
        return False

    # checks for periods, spaces, or punctuation marks
    for i in s:
        if i in [".", " ", "!", "?"]:
            return False

    # checks if numbers in string starts with 0
    i = 0
    while i < len(s):
        if s[i].isalpha() == False:
            if s[i] == "0":
                return False
            else:
                break
        i  = 1

    # after u see a valid number, no letter can come after it 
    # this is where the challenge is ,
    for i in range(len(s) - 1):
        if s[i].isdigit() and s[i   1].isalpha():
            return False

    # returns true if all the requirements are passed
    return True

CodePudding user response:

So, you don't have to go in reverse order to check if there's a letter. I would iterate over the letters until you get to a character that's a number. Once you do that, you can check that the rest of the characters are numbers.

If you did want to go in reverse, you can apply the same logic: iterate backwards, checking that you're only reading numbers. Once you hit a letter, check that the rest of the string is only letters. You can do this in multiple ways, such as using set operations or just checking the character is the correct type.

Also, note that you don't have to/shouldn't use True/False in the conditional statements. It's better to use something like if s[i].isalpha() and if not s[i].isalpha()

CodePudding user response:

First, find the index of the last letter, and the index of the first digit. Since no letters are allowed after numbers, the index of the last letter must be less than the index of the first digit:

def is_valid(s):
    ...

    first_digit_index = None
    last_letter_index = None

    for i, c in enumerate(s):
        if c.isalpha():
            last_letter_index = i

        # Only set first_digit_index if we haven't found a digit yet
        if c.isdigit() and first_digit_index is None:
            first_digit_index = i

    # ( at least one digit in input ) and ( last letter is after first digit )
    if first_digit_index is not None and last_letter_index > first_digit_index:
        return False

    ...

Here are a few other suggestions to clean up your code:

def is_valid(s):
  • First, check the length condition. It is the easiest to check since len(s) is already known and involves no slicing of the string or iteration.
    if not (2 <= len(s) <= 6): 
        return False
  • Next, check that the first two characters are alphabets:
    if not s[:2].isalpha():
        return False
  • Next, iterate over the input string to get the indices of the first digit and last alphabet as I showed above. Since we're already iterating over the string, we can use this to check that the first number is not zero, and that none of the characters are in our forbidden characters set. I defined this as a set instead of a list because it is faster to check if something is in a set than to check if it is in a list. This is especially useful if your set of forbidden characters is very large.
    forbidden_chars = {".", " ", "!", "?"}
    first_digit_index = None
    last_letter_index = None

    for i, c in enumerate(s):
        # If a character is invalid, we can return False right here!
        if c in forbidden_chars:
            return False

        if c.isalpha():
            last_letter_index = i

        # Only set first_digit_index if we haven't found a digit yet
        if c.isdigit() and first_digit_index is None:
            first_digit_index = i

            # We found the first digit, it was zero :(
            if c == '0':
                return False

    # ( at least one digit in input ) and ( last letter is after first digit )
    if first_digit_index is not None and last_letter_index > first_digit_index:
        return False
  • Now that we've checked all our conditions and none failed, we can:
    return True

CodePudding user response:

This could be a good use of regular expressions. This pattern only matches strings that have an optional group of letters followed by an optional group of numbers. The pattern also omits special characters by design.

import re

def is_valid(s):
    
    if len(s) < 2 or len(s) > 6:
        return False
    
    # regular expression with two capture groups
    pattern = "^([a-zA-Z]{0,6})([0-9]{0,6})$"
    m = re.match(pattern, s)
    
    if m is None:
        return False
    
    alpha = m.group(1)
    numeric = m.group(2)
    
    # first digit is not zero
    if numeric[0]=="0":
        return False
    
    return True
  • Related