You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)。正确的思路是先找出所有符合要求的数字(包括英文拼写和阿拉伯数字),再取第一个和最后一个,用正则表达式的正向预查可以完美处理重叠场景。

具体实现步骤:

  1. 定义数字映射表,把英文拼写对应到阿拉伯数字;
  2. 构建正则表达式,用正向预查(?=...)匹配所有可能的数字(预查不会消耗字符,因此能捕获重叠的匹配项);
  3. 对每行文本提取所有匹配结果,取首尾转换为数字后计算。

修改后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:24:53