Skip to content

Instantly share code, notes, and snippets.

@larsks
Last active January 29, 2024 16:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larsks/af1f8e3d97bf3dd35e1e6734463594cf to your computer and use it in GitHub Desktop.
Save larsks/af1f8e3d97bf3dd35e1e6734463594cf to your computer and use it in GitHub Desktop.
CS50 PS2 solution with tests

A couple of solutions to CS50 problem 2 ("vanity plates") along with a simple test suite.

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
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