Python字符串数字检测求助:Advent of Code数字拼写转换问题
解决Advent of Code中重叠数字拼写的匹配问题
我在玩Advent of Code游戏,规则是找出每行的第一个和最后一个有效数字——这里的数字包括阿拉伯数字,以及拼写为英文的数字(one、two、three、four、five、six、seven、eight、nine分别对应1-9)。第一天的题目用Python完成了,但第二天遇到了重叠拼写数字的处理问题:比如eightwothree需要提取8和3,xtwone3four需要提取2和4,zoneight234需要提取1和4,而我现有的代码用replace方法处理时,会破坏重叠部分的匹配,导致结果错误。尝试用正则表达式解决但不知道怎么写,附上现有代码寻求帮助。
def isInteger(s): try: int(s) except ValueError: return False else: return True def main(): # ASk user for the filename nomFichier = "" nomFichier = raw_input('Nom du fichier:') print "Opening file: " + nomFichier # Ouverture du fichier file1 = open(nomFichier, 'r') # les lignes sont lues et stored inside a variable Lines = file1.readlines() # if the first numeric has been detected firstValueDetected = 0 lastValueDetected = 0 firstValue = 0 lastValue = 0 countValue = 0 count = 0 totalLine = 0 total = 0 # Strips the newline character for line in Lines: count += 1 print("Line{}: {}".format(count, line.strip())) firstValueDetected = 0 lastValueDetected = 0 countValue=0 totalLine = 0 tmp_string = line.strip() tmp_string = tmp_string.replace("nine", "9") print "convert: " + tmp_string tmp_string = tmp_string.replace("eight", "8") print "convert: " + tmp_string tmp_string = tmp_string.replace("seven", "7") print "convert: " + tmp_string tmp_string = tmp_string.replace("six", "6") print "convert: " + tmp_string tmp_string = tmp_string.replace("five", "5") print "convert: " + tmp_string tmp_string = tmp_string.replace("four", "4") print "convert: " + tmp_string tmp_string = tmp_string.replace("three", "3") print "convert: " + tmp_string tmp_string = tmp_string.replace("two", "2") print "convert: " + tmp_string tmp_string = tmp_string.replace("one", "1") print "convert: " + tmp_string a_string = tmp_string for letter in a_string: print letter if isInteger(letter): print letter +" is numeric :-) " if firstValueDetected == 0: firstValue = int(letter) firstValueDetected = 1 else: lastValue = int(letter) countValue = countValue +1 if countValue == 1: lastValue = firstValue; totalLine = firstValue*10 + lastValue print "First Value is " + str(firstValue) + " and Last value is " + str(lastValue) + " => " + str(totalLine); total = total + totalLine # Closing files file1.close() print "Total : " + str(total) main()
解决方案
核心问题在于直接用replace会修改字符串,破坏重叠拼写的数字(比如twone替换two为2后,剩下的ne无法匹配one)。正确的思路是先找出所有符合要求的数字(包括英文拼写和阿拉伯数字),再取第一个和最后一个,用正则表达式的正向预查可以完美处理重叠场景。
具体实现步骤:
- 定义数字映射表,把英文拼写对应到阿拉伯数字;
- 构建正则表达式,用正向预查
(?=...)匹配所有可能的数字(预查不会消耗字符,因此能捕获重叠的匹配项); - 对每行文本提取所有匹配结果,取首尾转换为数字后计算。
修改后的代码
import re # 数字映射:英文拼写和阿拉伯数字都对应到数字字符串 digit_map = { 'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9' } def main(): nomFichier = raw_input('Nom du fichier:') print "Opening file: " + nomFichier with open(nomFichier, 'r') as file1: Lines = file1.readlines() count = 0 total = 0 # 正则模式:正向预查所有可能的数字(英文或阿拉伯) pattern = re.compile(r'(?=(one|two|three|four|five|six|seven|eight|nine|\d))') for line in Lines: count += 1 line_stripped = line.strip() print("Line{}: {}".format(count, line_stripped)) # 提取所有匹配的数字项 matches = pattern.findall(line_stripped) # 转换为数字字符串 digits = [digit_map[match] for match in matches] if digits: first_value = int(digits[0]) last_value = int(digits[-1]) total_line = first_value * 10 + last_value print "First Value is " + str(first_value) + " and Last value is " + str(last_value) + " => " + str(total_line) total += total_line print "Total : " + str(total) main()
关键说明:
- 正则表达式
(?=(one|two|three|four|five|six|seven|eight|nine|\d)):(?=...)是正向预查,它会检查当前位置后面是否有匹配的内容,但不会移动匹配指针,因此能捕获到重叠的数字(比如twone会匹配到two和one); - 使用
with open语句自动管理文件关闭,比手动close更安全; - 数字映射表同时包含英文拼写和阿拉伯数字,统一转换为数字字符串,简化后续处理。
内容的提问来源于stack exchange,提问作者Stéphane Purnelle
相关产品推荐
相关产品推荐

