A couple of solutions to CS50 problem 2 ("vanity plates") along with a simple test suite.
Last active
January 29, 2024 16:49
-
-
Save larsks/af1f8e3d97bf3dd35e1e6734463594cf to your computer and use it in GitHub Desktop.
CS50 PS2 solution with tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def is_valid_slicing(plate) -> bool: | |
'''Use string slicing and iteration to validate | |
license plates.''' | |
# Too short or too long | |
if len(plate) < 2 or len(plate) > 6: | |
return False | |
# Must start with two letters | |
if not plate[:2].isalpha(): | |
return False | |
# No punctuation, etc | |
if not plate.isalnum(): | |
return False | |
# First number cannot be 0, numbers must be | |
# at the end. | |
for i, c in enumerate(plate[2:], 2): | |
if c.isdecimal(): | |
if c == "0": | |
return False | |
if not plate[i:].isdecimal(): | |
return False | |
break | |
return True | |
def is_valid_statemachine(plate) -> bool: | |
'''Use a state machine to valid license plates.''' | |
# vanity plates may contain a maximum of 6 characters | |
# and a minimum of 2 characters | |
if len(plate) < 2 or len(plate) > 6: | |
return False | |
state = 0 | |
for i, c in enumerate(plate): | |
# vanity plates may contain...letters or numbers | |
# No periods, spaces, or punctuation marks are allowed | |
if not (c.isdecimal() or c.isalpha()): | |
return False | |
if state == 0: | |
# All vanity plates must start with at least two letters | |
if c.isdecimal(): | |
return False | |
if i == 1: | |
state = 1 | |
elif state == 1: | |
# If we find a number, everything else needs to be numbers | |
if c.isdigit(): | |
# First number used cannot be '0' | |
if c == "0": | |
return False | |
state = 2 | |
elif state == 2: | |
# Letters after numbers is not allowed | |
if c.isalpha(): | |
return False | |
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pytest | |
from plates import is_valid_slicing, is_valid_statemachine | |
test_cases = ( | |
("A", False), # Too short | |
("111111", False), # Does not start with letters | |
("22AAAA", False), # Does not start with letters | |
("AA..AA", False), # Contains non-alphanumerics | |
("AA0000", False), # The first number used cannot be 0 | |
("A22222", False), # Must start with two letters | |
("AA22AA", False), # Numbers cannot be in middle | |
("AAAAAAA", False), # Too long | |
("aaaaaaa", False), # Letters must be uppercase | |
("AA", True), | |
("AA2222", True), | |
("AAAAAA", True), | |
# Test cases from https://cs50.harvard.edu/python/2022/psets/2/plates/ | |
("CS50", True), | |
("CS05", False), | |
("CS50P", False), | |
("PI3.14", False), | |
("H", False), | |
("OUTATIME", False), | |
# What about non-English characters? The RMV isn't actually | |
# explicit about what constitutes a valid character set, so | |
# these are technically valid. | |
("NIÑO", True), | |
("김세정", True), | |
) | |
@pytest.mark.parametrize( | |
"plate,valid", test_cases, | |
) | |
def test_is_valid_slicing(plate, valid): | |
assert is_valid_slicing(plate) == valid | |
@pytest.mark.parametrize( | |
"plate,valid", test_cases, | |
) | |
def test_is_valid_statemachine(plate, valid): | |
assert is_valid_statemachine(plate) == valid |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment