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

Rust regex引擎如何处理重叠匹配?(AoC2023 Day1问题)

解决Advent of Code 2023 Day1第二部分的重叠数字匹配问题

你遇到的threeight这类重叠拼写数字的匹配问题,核心是标准非重叠正则匹配会漏掉重叠部分的第二个数字(比如只会匹配three,忽略后面的eight),而Rust的regex crate不支持环视语法,这里提供两种可行的解决思路:

方案1:遍历每个起始位置收集所有匹配

直接遍历字符串的每个索引,从每个位置尝试匹配数字正则,收集所有成功匹配的数字,最后取第一个和最后一个计算校准值。这种方式能捕获所有重叠的匹配项。

use regex::Regex;

// 将匹配到的字符串转换为对应数字
fn str_to_digit(s: &str) -> Option<u32> {
    match s {
        "0" | "zero" => Some(0),
        "1" | "one" => Some(1),
        "2" | "two" => Some(2),
        "3" | "three" => Some(3),
        "4" | "four" => Some(4),
        "5" | "five" => Some(5),
        "6" | "six" => Some(6),
        "7" | "seven" => Some(7),
        "8" | "eight" => Some(8),
        "9" | "nine" => Some(9),
        _ => None,
    }
}

fn calculate_calibration(line: &str) -> u32 {
    let digit_re = Regex::new(r"[0-9]|zero|one|two|three|four|five|six|seven|eight|nine").unwrap();
    let mut digits = Vec::new();

    // 遍历每个字符位置,尝试匹配数字
    for start in 0..line.len() {
        if let Some(matched) = digit_re.find(&line[start..]) {
            if let Some(digit) = str_to_digit(matched.as_str()) {
                digits.push(digit);
            }
        }
    }

    // 取第一个和最后一个数字计算结果
    digits.first().unwrap() * 10 + digits.last().unwrap()
}

方案2:反转字符串匹配最后一个数字

因为我们只需要第一个和最后一个数字,可以拆分处理:

  • 第一个数字:用原正则从左到右匹配第一个结果
  • 最后一个数字:将字符串反转,用反转后的数字正则匹配第一个结果,再转换回原数字

这种方法效率更高,无需遍历所有位置。

use regex::Regex;

// 正向字符串转数字
fn str_to_digit(s: &str) -> u32 {
    match s {
        "0" | "zero" => 0,
        "1" | "one" => 1,
        "2" | "two" => 2,
        "3" | "three" => 3,
        "4" | "four" => 4,
        "5" | "five" => 5,
        "6" | "six" => 6,
        "7" | "seven" => 7,
        "8" | "eight" => 8,
        "9" | "nine" => 9,
        _ => unreachable!("Invalid digit string"),
    }
}

// 反转后的字符串转数字
fn reversed_str_to_digit(s: &str) -> u32 {
    match s {
        "0" | "orez" => 0,
        "1" | "eno" => 1,
        "2" | "owt" => 2,
        "3" | "eerht" => 3,
        "4" | "ruof" => 4,
        "5" | "evif" => 5,
        "6" | "xis" => 6,
        "7" | "neves" => 7,
        "8" | "thgie" => 8,
        "9" | "enin" => 9,
        _ => unreachable!("Invalid reversed digit string"),
    }
}

fn get_first_digit(line: &str) -> u32 {
    let re = Regex::new(r"[0-9]|zero|one|two|three|four|five|six|seven|eight|nine").unwrap();
    str_to_digit(re.find(line).unwrap().as_str())
}

fn get_last_digit(line: &str) -> u32 {
    let reversed_line: String = line.chars().rev().collect();
    let re = Regex::new(r"[0-9]|orez|eno|owt|eerht|ruof|evif|xis|neves|thgie|enin").unwrap();
    reversed_str_to_digit(re.find(&reversed_line).unwrap().as_str())
}

fn calculate_calibration(line: &str) -> u32 {
    get_first_digit(line) * 10 + get_last_digit(line)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:33:09