diff --git a/src/bin/day1.rs b/src/bin/day1.rs index 246399d..15e68e1 100644 --- a/src/bin/day1.rs +++ b/src/bin/day1.rs @@ -2,13 +2,103 @@ use aoc23::read; use chumsky::prelude::*; +use std::{io::{BufReader, BufRead}, fs::File}; +use chumsky::chain::Chain; -fn parser() -> impl Parser> { - end() +struct Line { + first_digit: u128, + last_digit: u128 +} + +// thanks rust +fn array(array: &'static [T; N]) -> &'static [T] { + array +} + +impl Line { + fn parser() -> impl Parser> { + choice(( + // digit combinations (only the relevant ones) + just("oneight").map(|_| array(&[1, 8])), + just("twoone").map(|_| array(&[2, 1])), + just("eightwo").map(|_| array(&[8, 2])), + + // single digits + just("one").or(just("1")).map(|_| array(&[1])), + just("two").or(just("2")).map(|_| array(&[2])), + just("three").or(just("3")).map(|_| array(&[3])), + just("four").or(just("4")).map(|_| array(&[4])), + just("five").or(just("5")).map(|_| array(&[5])), + just("six").or(just("6")).map(|_| array(&[6])), + just("seven").or(just("7")).map(|_| array(&[7])), + just("eight").or(just("8")).map(|_| array(&[8])), + just("nine").or(just("9")).map(|_| array(&[9])), + + // garbage + none_of(['1', '2', '3', '4', '5', '6', '7', '8', '9', '\n']) + .map(|_| array(&[])) + )) + .repeated() + .then_ignore(just('\n')) + .map(|digits: Vec<&'static [u128]>| { + let mut digits = digits.into_iter().flat_map(|array| array.iter().copied()); + let first_digit = digits.next().expect("No digit in line"); + let last_digit = digits.last().unwrap_or(first_digit); + Line { + first_digit, + last_digit + } + }) + } +} + +fn parser() -> impl Parser, Error = Simple> { + Line::parser().repeated().then_ignore(end()) } fn main() -> anyhow::Result<()> { - let _ = read("input.txt", parser())?; + let lines = read("inputs/day1.txt", parser())?; + + let sum: u128 = lines + .iter() + .map(|line| line.first_digit * 10 + line.last_digit) + // .map(|number| { eprintln!("{number}"); number }) + .sum(); + println!("{sum}"); + + let mut sum: u128 = 0; + for line in BufReader::new(File::open("inputs/day1.txt")?).lines() { + let line = line?; + let line = line.trim(); + if line.is_empty() { + continue; + } + + let mut digits = Vec::new(); + for i in 0 .. line.len() { + let s = &line[i..]; + + macro_rules! check_digit { + ($digit:literal, $string:literal) => { + if s.starts_with(stringify!($digit)) || line[i..].starts_with($string) { + digits.push($digit); + } + } + } + + check_digit!(1, "one"); + check_digit!(2, "two"); + check_digit!(3, "three"); + check_digit!(4, "four"); + check_digit!(5, "five"); + check_digit!(6, "six"); + check_digit!(7, "seven"); + check_digit!(8, "eight"); + check_digit!(9, "nine"); + } + sum += digits.first().unwrap() * 10 + digits.last().unwrap(); + } + println!("{sum}"); Ok(()) }