英文:
A particular data value does not yield the answer i was expecting
问题
这是一个用于检查车牌号条件的程序:
- 所有个性化车牌号必须以至少两个字母开头。
- 个性化车牌号最多可以包含6个字符(字母或数字),最少要有2个字符。
- 数字不能出现在车牌号的中间,必须出现在末尾。例如,AAA222是一个合格的个性化车牌号;AAA22A是不合格的。第一个数字不能是'0'。
- 不允许使用句点、空格或标点符号。
当我输入'PK40'时,它输出'invalid',但应该输出'valid',我做错了什么?
这是我的代码:
def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")
def is_valid(s):
if check_length(s) and start_with_letters(s) and zero_check(s) and no_punctuation(s):
return True
else:
return False
def check_length(s):
if 2 <= len(s) < 7:
return True
else:
return False
def start_with_letters(s):
if s[0:2].isalpha():
return True
else:
return False
def zero_check(s):
index = 0
while index < len(s):
if not s[index].isalpha():
if s[index] == "0":
return False
else:
break
index += 1
def no_punctuation(s):
i = 2
punctuation = 0
while i < len(s) and punctuation == 0:
char = s[i]
if not char.isalpha():
if not char.isdigit():
punctuation += 1
i += 1
if punctuation == 0:
return True
else:
return False
main()
请注意,我已经修复了一些代码中的错误,并将一些冗余的条件检查简化为更紧凑的形式。希望这个修复后的代码可以正确判断车牌号是否有效。
英文:
This is a program that is supposed to check following conditions for a number plates:
- 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.
Now, when I enter 'PK40' it yields 'invalid' but it is supposed to print 'valid' what am i doing wrong?
this is my code:
def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")
def is_valid(s):
check_length(s)
if check_length(s):
start_with_letters(s)
if start_with_letters(s):
zero_check(s)
if zero_check(s):
no_punctuation(s)
if no_punctuation(s):
return True
else:
return False
else:
return False
else:
return False
else:
return False
def check_length(str):
if len(str)>= 2 and len(str)< 7:
return True
else:
return False
def start_with_letters(str1):
if str1[0:2].isalpha():
return True
else:
return False
def zero_check(str2):
index = 0
while index < len(str2): #inedx starts from 0 but len starts from 1, thus 'less than'
if str2[index].isalpha() == False: #AAA23A returns false at index = 3
if str2[index] == "0":
return False
else:
break #because there is no 0 in the string
index = index + 1
def no_punctuation(str3):
i = 2
punctuation = 0
while i < len(str3) and punctuation == 0:
char = str3[i]
if char.isalpha() == False: #if no alphabet is found, check for numbers
if char.isdigit() == False: #no digits
punctuation += 1
i =+ 1
if punctuation == 0:
return True
else:
return False
main()
答案1
得分: 1
zero_check
方法在成功的情况下没有返回一个真值。它有一个默认返回None
,这被计算为False
。你想要的是:
def zero_check(str2):
index = 0
while index < len(str2): # index从0开始,但len从1开始,因此应该是'小于'
if str2[index].isalpha() == False: # AAA23A在索引3处返回False
if str2[index] == "0":
return False
else:
break # 因为字符串中没有0
index = index + 1
return True
no_punctuation
调用i =+ 1
(即i = +1
或i = 1
),而应该是i += 1
:
def no_punctuation(str3):
i = 2
punctuation = 0
while i < len(str3) and punctuation == 0:
char = str3[i]
if char.isalpha() == False: # 如果没有字母,则检查数字
if char.isdigit() == False: # 没有数字
punctuation += 1
i += 1
if punctuation == 0:
return True
else:
return False
一些改进。isalpha
和isdigit
可能会产生误导。例如:
>>> "⑴".isdigit()
True
>>> "à".isalpha()
True
在这些情况下,更加细致的检查会更安全:
def is_letter(c):
return "A" <= c <= "Z"
def is_number(c):
return "0" <= c <= "9"
进一步说,我建议将你列出的每种情况分解为各自的方法。你还可以使用for c in s:
的语法来更清晰地迭代字符串。你的主要is_valid
方法可以简单地将所有调用的结果组合在一起:
def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")
def is_valid(s):
return (
correct_length(s)
and two_letter_start(s)
and no_letters_after_numbers(s)
and all_letters_or_numbers(s)
)
def correct_length(s):
"""
Vanity plates may contain a maximum of 6 characters (letters or numbers) and a minimum of 2 characters.
"""
return 2 <= len(s) <= 6
def two_letter_start(s):
"""
All vanity plates must start with at least two letters.
"""
return is_letter(s[0]) and is_letter(s[1])
def no_letters_after_numbers(s):
"""
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’.
"""
number_found = False
for c in s:
if not number_found:
# The first number used cannot be a ‘0’.
if c == "0":
return False
if is_number(c):
number_found = True
else:
# Numbers cannot be used in the middle of a plate
if is_letter(c):
return False
return True
def all_letters_or_numbers(s):
"""
No periods, spaces, or punctuation marks are allowed.
"""
for c in s:
if not (is_letter(c) or is_number(c)):
return False
return True
def is_letter(c):
return "A" <= c <= "Z"
def is_number(c):
return "0" <= c <= "9"
if __name__ == "__main__":
main()
最后,使用正则表达式,你可以将其简化为一行:
import re
def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")
def is_valid(s):
return re.match(r"^(?=[A-Z0-9]{2,6}$)[A-Z]{2}[A-Z]*([1-9][0-9]*)?$", s)
分解:
^ 字符串的开始。
(?= 前瞻以便我们可以断定额外的条件。
[A-Z0-9]{2,6} 将包含2-6个字母或数字。
$ 然后字符串将结束。
)
[A-Z]{2} 前两个字符是字母。
[A-Z]* 后面可以有更多的字母。
(
[1-9] 如果有数字,它们以1-9开头
[0-9]* 然后我们可以有任意数量的0-9数字
)? 数字是可选的。
$ 字符串然后结束。
英文:
- the
zero_check
method does not return a truthy value in the success case. It has a default return ofNone
which evaluates toFalse
. You want:
def zero_check(str2):
index = 0
while index < len(str2): #inedx starts from 0 but len starts from 1, thus 'less than'
if str2[index].isalpha() == False: #AAA23A returns false at index = 3
if str2[index] == "0":
return False
else:
break #because there is no 0 in the string
index = index + 1
return True
no_punctuation
callsi =+ 1
(i.e.i = +1
ori = 1
) when it should bei += 1
def no_punctuation(str3):
i = 2
punctuation = 0
while i < len(str3) and punctuation == 0:
char = str3[i]
if char.isalpha() == False: #if no alphabet is found, check for numbers
if char.isdigit() == False: #no digits
punctuation += 1
i += 1
if punctuation == 0:
return True
else:
return False
Some improvements. isalpha
and isdigit
can be very misleading. For example:
>>> "⑴".isdigit()
True
>>> "à".isalpha()
True
Its better to be more granular in these cases. Using the range of ascii values would be safer:
def is_letter(c):
return "A" <= c <= "Z"
def is_number(c):
return "0" <= c <= "9"
Going further, I would break down each case you listed into their own method. You can also iterate through a string with the syntax for c in s:
which will make this much cleaner. Your main is_valid
method can simply combine the results of all calls together:
def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")
def is_valid(s):
return (
correct_length(s)
and two_letter_start(s)
and no_letters_after_numbers(s)
and all_letters_or_numbers(s)
)
def correct_length(s):
"""
Vanity plates may contain a maximum of 6 characters (letters or numbers) and a minimum of 2 characters.
"""
return 2 <= len(s) <= 6
def two_letter_start(s):
"""
All vanity plates must start with at least two letters.
"""
return is_letter(s[0]) and is_letter(s[1])
def no_letters_after_numbers(s):
"""
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’.
"""
number_found = False
for c in s:
if not number_found:
# The first number used cannot be a ‘0’.
if c == "0":
return False
if is_number(c):
number_found = True
else:
# Numbers cannot be used in the middle of a plate
if is_letter(c):
return False
return True
def all_letters_or_numbers(s):
"""
No periods, spaces, or punctuation marks are allowed.
"""
for c in s:
if not (is_letter(c) or is_number(c)):
return False
return True
def is_letter(c):
return "A" <= c <= "Z"
def is_number(c):
return "0" <= c <= "9"
if __name__ == "__main__":
main()
Finally, using a regex, you can make this a one-liner:
import re
def main():
plate = input("Plate: ")
if is_valid(plate):
print("Valid")
else:
print("Invalid")
def is_valid(s):
return re.match(r"^(?=[A-Z0-9]{2,6}$)[A-Z]{2}[A-Z]*([1-9][0-9]*)?$", s)
Breakdown:
^ Start of the string.
(?= Lookahead so we can assert an extra condition.
[A-Z0-9]{2,6} There will 2-6 letters or numbers.
$ Then the string will end.
)
[A-Z]{2} The first two characters are letters.
[A-Z]* There can be more letters to follow.
(
[1-9] If there are numbers, they start with 1-9
[0-9]* Then we can have any amount of 0-9 digits
)? The digits are optional.
$ Then the string ends.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论