import re def clean_date_line(line: str) -> str: # 1) Replace "1)" with "0" cleaned = line.replace("1)", "0") # 2) Replace "()" with "0" cleaned = cleaned.replace("()", "0") # Clean BB misrecognitions (convert B8, 8B, 88 to BB when followed by digits) cleaned = re.sub(r'\b(?:B8|8B|88)(?=\d)', 'BB', cleaned) cleaned = re.sub(r'^(?:B8|8B|88)(?=\d)', 'BB', cleaned) # Clean 012 month misrecognition (e.g. 020122027 -> 02022027) cleaned = re.sub(r'(?02\g<2>', cleaned) cleaned = re.sub(r'(?\g<2>02\g<3>\g<4>', cleaned) # Clean 112 month misrecognition (e.g. 021122027 -> 02022027) cleaned = re.sub(r'(?02\g<2>', cleaned) cleaned = re.sub(r'(?\g<2>02\g<3>\g<4>', cleaned) # Run contextual replacements for _ in range(3): # letter o/O flanked by digits or boundary -> 0 cleaned = re.compile(r'(\d)[oO](\d|\b)').sub(r'\g<1>0\g<2>', cleaned) cleaned = re.compile(r'(\b|\d)[oO](\d)').sub(r'\g<1>0\g<2>', cleaned) # letter I/i/l/| flanked by digits -> 1 cleaned = re.compile(r'(\d)[Ii|l](\d|\b)').sub(r'\g<1>1\g<2>', cleaned) cleaned = re.compile(r'(\b|\d)[Ii|l](\d)').sub(r'\g<1>1\g<2>', cleaned) # letter S/s flanked by digits -> 5 cleaned = re.compile(r'(\d)[Ss](\d|\b)').sub(r'\g<1>5\g<2>', cleaned) cleaned = re.compile(r'(\b|\d)[Ss](\d)').sub(r'\g<1>5\g<2>', cleaned) # letter Z/z flanked by digits -> 2 cleaned = re.compile(r'(\d)[Zz](\d|\b)').sub(r'\g<1>2\g<2>', cleaned) cleaned = re.compile(r'(\b|\d)[Zz](\d)').sub(r'\g<1>2\g<2>', cleaned) # letter B flanked by digits -> 8 cleaned = re.compile(r'(\d)B(\d|\b)').sub(r'\g<1>8\g<2>', cleaned) cleaned = re.compile(r'(\b|\d)B(\d)').sub(r'\g<1>8\g<2>', cleaned) return cleaned test_cases = [ "231)92026", "23o92026", "23O92026", "2309202l", "2309202I", "230920Z6", "230920s6", "2309202B", "BB 231)92026", "BB: 23()92026", "12010111", "B8021122027", "88021122027", "020122027", "BB 02/012/2027", "021122027", "BB 02/112/2027" ] for tc in test_cases: cleaned = clean_date_line(tc) print(f"Original: {tc:<18} -> Cleaned: {cleaned}")