use std::{ fs::File, io::{BufReader, Read}, path::Path, }; use nom::{ bytes::complete::tag, character::complete::i32, sequence::{delimited, separated_pair}, IResult, }; #[derive(Debug)] struct Mul { left: i32, right: i32, } fn parse_int32_pair(input: &str) -> IResult<&str, (i32, i32)> { separated_pair(i32, tag(","), i32)(input) } fn parse_mul(input: &str) -> IResult<&str, Mul> { let (rem, (left, right)) = delimited(tag("mul("), parse_int32_pair, tag(")"))(input)?; Ok((rem, Mul { left, right })) } pub(super) fn part_one(input: &Path) -> anyhow::Result { let mut reader = BufReader::new(File::open(input)?); let mut buf = String::new(); reader.read_to_string(&mut buf)?; let mut answer = 0; loop { if buf.len() < 5 { break; } let (rem, mul) = match parse_mul(&buf) { Ok((rem, mul)) => (rem, mul), Err(_) => { buf.replace_range(0..1, ""); continue; } }; buf = rem.into(); answer += mul.left * mul.right; } Ok(answer) }