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

Advent of Code 2023 Day1 Part2代码求助:测试通过输入计算错误

Advent of Code 2023 Day1 Part2 问题排查

我正在做2023年的Advent of Code,卡在了Day1 Part2的问题上。题目要求提取字符串中的首尾数字(英文数字如one也视为有效数字),将首尾数字组合成两位数后求和。我的代码在给定的测试数据中能得到正确结果281,但用官方输入数据计算出的总和54489是错误的,恳请帮忙指出错误所在。

测试数据示例

const testString: string[] = [
    "two1nine",
    "eightwothree",
    "abcone2threexyz",
    "xtwone3four",
    "4nineeightseven2",
    "zoneight234",
    "7pqrstsixteen",
];

我的代码

const partTwo = () => {
  const testString: string[] = [
    "two1nine",
    "eightwothree",
    "abcone2threexyz",
    "xtwone3four",
    "4nineeightseven2",
    "zoneight234",
    "7pqrstsixteen",
  ];

  const filePath = "data.txt";
  const dataArray: string[] = fs
    .readFileSync(filePath)
    .toString()
    .split("\n")
    .map((str: string) => str.replace("\r", ""));

  const numberMapping: Map<string, number> = new Map([
    ["one", 1],
    ["two", 2],
    ["three", 3],
    ["four", 4],
    ["five", 5],
    ["six", 6],
    ["seven", 7],
    ["eight", 8],
    ["nine", 9],
  ]);

  const convertToInteger = (str: string): number => {
    const regexPattern = Array.from(numberMapping.keys()).join("|") + "|\\d";
    const regex = new RegExp(regexPattern, "g");
    const foundWords = str.match(regex);

    if (!foundWords || foundWords.length === 0) return 0;

    console.log(foundWords);

    const first = isNaN(parseInt(foundWords[0]))
      ? numberMapping.get(foundWords[0])
      : parseInt(foundWords[0]);
    const last = isNaN(parseInt(foundWords[foundWords.length - 1]))
      ? numberMapping.get(foundWords[foundWords.length - 1])
      : parseInt(foundWords[foundWords.length - 1]);

    return (first ?? 0) * 10 + (last ?? 0);
  };

  const getTotalSum = (arr: number[]) => {
    return arr.reduce((acc, curr) => acc + curr, 0);
  }

  const result = dataArray.map((str) => convertToInteger(str));
  const resultNumber = getTotalSum(result);

  const resultMap: Record<string, number> = {};
  dataArray.forEach((str) => {
    resultMap[str] = convertToInteger(str);
  });

  result.forEach((str, i) => console.log(`${dataArray[i]} - ${str}`));
  console.log(result);
  console.log(resultNumber);
};

部分计算结果

2qlljdqcbeight - 28
eight47srvbfive - 85
slconeightfoureight557m38 - 18
xvqeightwosixnine61eightsn2tdczfhx - 82
msixonexch1twokjbdlhchqk1 - 61
112ninejlhhjmjzkzgdsix - 16
6six7jr - 67
878eightgvsqvzfthree - 83
2jxzhlkhdktxfjjleightdfpgfxjv - 28
mxbzgzg5three - 53
33fivehcxcxhsqhtwo - 32
bhfive4ths1811seven - 57
eightfxkpsqjlpjgjcp12twoxkhllqzq7 - 87
sixkvvhvgtcnjhjtmxnr7seven8 - 68
csdeightwobtsxflml4eightbxbzmvhq2four - 84
twoplpbhq3mkkhb2 - 22
1sevenrsgrl76rqtsqqzkncrgznine - 19
6twolnlq - 62
nine567 - 97
qjvhrrtdqgsp8pxrlslvtwothree9three3 - 83
ninekxpninedjx7phcncpzq - 97
onegmzclftbt8sixmkfnqpeight - 18
one53foureightzpvseven9 - 19
315foursixonefcvttgrknrgf1 - 31
and more... 

错误原因分析

问题出在正则表达式的匹配逻辑上:当前使用的全局正则/one|two|...|nine|\d/g会从上次匹配结束的位置继续匹配,无法处理重叠的数字字符串。

比如字符串oneight,它同时包含one和eight,但正则会先匹配one,然后指针跳到one之后的位置(即i的位置),剩下的ight无法匹配到eight,导致最终取到的首尾数字都是one对应的1,得到错误的11,而正确结果应该是18。

类似的重叠场景还有twone(包含two和one)、threeight(包含three和eight)等,这些情况在官方输入中大概率存在,导致总和计算错误。

修正方案

使用**正向预查(lookahead)**实现重叠匹配,让正则可以在每个位置检查是否存在匹配的数字(无论是英文还是阿拉伯数字),而不会移动匹配指针。修改convertToInteger函数中的正则匹配逻辑:

const convertToInteger = (str: string): number => {
  const regex = new RegExp(`(?=(${Array.from(numberMapping.keys()).join("|")}|\\d))`, "g");
  const foundWords: string[] = [];
  let match: RegExpExecArray | null;

  // 循环捕获所有匹配的数字(包括重叠的)
  while ((match = regex.exec(str)) !== null) {
    if (match[1]) {
      foundWords.push(match[1]);
    }
  }

  if (foundWords.length === 0) return 0;

  const first = isNaN(parseInt(foundWords[0]))
    ? numberMapping.get(foundWords[0])
    : parseInt(foundWords[0]);
  const last = isNaN(parseInt(foundWords[foundWords.length - 1]))
    ? numberMapping.get(foundWords[foundWords.length - 1])
    : parseInt(foundWords[foundWords.length - 1]);

  return (first ?? 0) * 10 + (last ?? 0);
};

这个修改后的逻辑会遍历字符串的每个位置,通过正向预查捕获所有可能的数字(包括重叠的),确保不会漏掉任何应该被识别的首尾数字。

内容的提问来源于stack exchange,提问作者Sitthata

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:32:34