diff --git a/rust/Cargo.lock b/rust/Cargo.lock index eee204e..76da661 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -5,3 +5,21 @@ version = 4 [[package]] name = "aoc" version = "0.1.0" +dependencies = [ + "nom", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f2cd264..b8165a4 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -8,3 +8,4 @@ path = "main.rs" name = "aoc" [dependencies] +nom = "8.0.0" diff --git a/rust/puzzles/day1.rs b/rust/puzzles/day1.rs index dd04b67..858d5a3 100644 --- a/rust/puzzles/day1.rs +++ b/rust/puzzles/day1.rs @@ -1,21 +1,36 @@ use crate::puzzle::Puzzle; +use nom::{ + Parser, + branch::alt, + character::complete::{char, digit1, newline}, + combinator::{eof, map_res, value}, + error::Error, + multi::separated_list1, + sequence::{pair, terminated}, +}; pub const PUZZLE: Puzzle, i32, 2> = Puzzle { number: 1, parser: |input| { - input - .lines() - .filter(|line| !line.is_empty()) - .map(|line| { - let d = match line.chars().next().unwrap() { - 'L' => Direction::L, - 'R' => Direction::R, - c => panic!("Unknown direction: {}", c), - }; - let i: i32 = line[1..].parse().unwrap(); - (d, i) - }) - .collect() + terminated( + terminated( + separated_list1( + newline, + pair( + alt(( + value(Direction::L, char('L')), + value(Direction::R, char('R')), + )), + parse_int(), + ), + ), + newline, + ), + eof, + ) + .parse(input) + .unwrap() + .1 }, parts: [ |instructions| { @@ -68,3 +83,7 @@ fn step(i: i32, d: Direction, p: i32) -> (i32, i32) { }; (p1.div_euclid(100), p1.rem_euclid(100)) } + +fn parse_int<'a>() -> impl Parser<&'a str, Output = i32, Error = Error<&'a str>> { + map_res(digit1, |s: &str| s.parse::()) +} diff --git a/rust/puzzles/day2.rs b/rust/puzzles/day2.rs index 3d2866f..7ea3bf5 100644 --- a/rust/puzzles/day2.rs +++ b/rust/puzzles/day2.rs @@ -1,23 +1,29 @@ use crate::puzzle::Puzzle; +use nom::{ + Parser, + character::complete::{char, digit1, newline}, + combinator::{eof, map_res}, + error::Error, + multi::separated_list1, + sequence::{separated_pair, terminated}, +}; pub const PUZZLE: Puzzle, usize, 2> = Puzzle { number: 2, - parser: |input| { - input - .strip_suffix("\n") - .unwrap() - .split(',') - .map(|range| { - match range - .split('-') - .map(|n| n.parse().unwrap()) - .collect::>()[..] - { - [a, b] => (a, b), - _ => panic!(), - } - }) - .collect() + parser: |input| -> Vec<(usize, usize)> { + terminated( + terminated( + separated_list1( + char(','), + separated_pair(parse_int(), char('-'), parse_int()), + ), + newline, + ), + eof, + ) + .parse(input) + .unwrap() + .1 }, parts: [ |input| { @@ -62,3 +68,7 @@ fn equal_chunks(n: &String, i: usize) -> bool { Some(x) => chunks.all(|y| y == x), } } + +fn parse_int<'a>() -> impl Parser<&'a str, Output = usize, Error = Error<&'a str>> { + map_res(digit1, |s: &str| s.parse::()) +}