Switch day3b to a nom parser
This commit is contained in:
parent
e121e53258
commit
c170aee068
|
@ -15,6 +15,7 @@ dependencies = [
|
||||||
name = "aoc-2024"
|
name = "aoc-2024"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"nom",
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -24,6 +25,22 @@ version = "2.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
|
|
|
@ -4,4 +4,5 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
nom = "7.1.3"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use nom::{
|
||||||
|
branch::alt, bytes::complete::{tag, take_while}, character::{complete::anychar, is_digit}, combinator::eof, multi::{many1, many_till}, Err, Finish, IResult
|
||||||
|
};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
const INPUT: &'static str = include_str!("../data/day3.txt");
|
const INPUT: &'static str = include_str!("../data/day3.txt");
|
||||||
|
@ -17,7 +20,10 @@ struct State {
|
||||||
|
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self{ mult_enabled: true, value: 0 }
|
Self {
|
||||||
|
mult_enabled: true,
|
||||||
|
value: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +31,7 @@ impl Default for State {
|
||||||
enum Operation {
|
enum Operation {
|
||||||
Do,
|
Do,
|
||||||
Dont,
|
Dont,
|
||||||
Mult(Multiplication)
|
Mult(Multiplication),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operation {
|
impl Operation {
|
||||||
|
@ -39,7 +45,7 @@ impl Operation {
|
||||||
state.mult_enabled = false;
|
state.mult_enabled = false;
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
Operation::Mult(mul) => mul.run(state)
|
Operation::Mult(mul) => mul.run(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,28 +67,13 @@ impl Multiplication {
|
||||||
|
|
||||||
fn parse_input_a(input: &str) -> Vec<Operation> {
|
fn parse_input_a(input: &str) -> Vec<Operation> {
|
||||||
let re = Regex::new(r"mul\(([0-9]{1,3}),([0-9]{1,3})\)").unwrap();
|
let re = Regex::new(r"mul\(([0-9]{1,3}),([0-9]{1,3})\)").unwrap();
|
||||||
re.captures_iter(input).map(|capture| {
|
re.captures_iter(input)
|
||||||
|
.map(|capture| {
|
||||||
let x = capture.get(1).unwrap().as_str().parse::<i32>().unwrap();
|
let x = capture.get(1).unwrap().as_str().parse::<i32>().unwrap();
|
||||||
let y = capture.get(2).unwrap().as_str().parse::<i32>().unwrap();
|
let y = capture.get(2).unwrap().as_str().parse::<i32>().unwrap();
|
||||||
Operation::Mult(Multiplication{ x, y })
|
Operation::Mult(Multiplication { x, y })
|
||||||
}).collect::<Vec<Operation>>()
|
})
|
||||||
}
|
.collect::<Vec<Operation>>()
|
||||||
|
|
||||||
fn parse_input_b(input: &str) -> Vec<Operation> {
|
|
||||||
let operation_re = Regex::new(r"do\(\)|don't\(\)|mul\(([0-9]{1,3}),([0-9]{1,3})\)").unwrap();
|
|
||||||
|
|
||||||
operation_re.captures_iter(input).map(|capture| {
|
|
||||||
match capture.get(0).unwrap().as_str()[0..4].as_ref() {
|
|
||||||
"do()" => Operation::Do,
|
|
||||||
"don'" => Operation::Dont,
|
|
||||||
"mul(" => {
|
|
||||||
let x = capture.get(1).unwrap().as_str().parse::<i32>().unwrap();
|
|
||||||
let y = capture.get(2).unwrap().as_str().parse::<i32>().unwrap();
|
|
||||||
Operation::Mult(Multiplication{ x, y })
|
|
||||||
}
|
|
||||||
_ => unimplemented!()
|
|
||||||
}
|
|
||||||
}).collect::<Vec<Operation>>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_part(lst: Vec<Operation>) -> i32 {
|
fn calculate_part(lst: Vec<Operation>) -> i32 {
|
||||||
|
@ -95,12 +86,53 @@ fn calculate_part(lst: Vec<Operation>) -> i32 {
|
||||||
state.value
|
state.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_input_b(input: &str) -> Vec<Operation> {
|
||||||
|
match many1(next_operation)(input).finish() {
|
||||||
|
Ok((_, operations)) => operations,
|
||||||
|
v => panic!("something went wrong: {:?}", v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_operation(input: &str) -> IResult<&str, Operation> {
|
||||||
|
let (rest, (_discard, operation)) = many_till(anychar, match_operation)(input)?;
|
||||||
|
Ok((rest, operation))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_operation(input: &str) -> IResult<&str, Operation> {
|
||||||
|
alt((match_do, match_dont, match_mult))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_do(input: &str) -> IResult<&str, Operation> {
|
||||||
|
let (rest, _) = tag("do()")(input)?;
|
||||||
|
Ok((rest, Operation::Do))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_dont(input: &str) -> IResult<&str, Operation> {
|
||||||
|
let (rest, _) = tag("don't()")(input)?;
|
||||||
|
Ok((rest, Operation::Dont))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_mult(input: &str) -> IResult<&str, Operation> {
|
||||||
|
let (rest, _) = tag("mul(")(input)?;
|
||||||
|
let (rest, x) = take_while(|c| is_digit(c as u8))(rest)?;
|
||||||
|
let (rest, _) = tag(",")(rest)?;
|
||||||
|
let (rest, y) = take_while(|c| is_digit(c as u8))(rest)?;
|
||||||
|
let (rest, _) = tag(")")(rest)?;
|
||||||
|
|
||||||
|
Ok((rest, Operation::Mult(Multiplication {
|
||||||
|
x: x.parse::<i32>().unwrap(),
|
||||||
|
y: y.parse::<i32>().unwrap(),
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const TEST_INPUT_A: &'static str = "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))";
|
const TEST_INPUT_A: &'static str =
|
||||||
const TEST_INPUT_B: &'static str = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))";
|
"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))";
|
||||||
|
const TEST_INPUT_B: &'static str =
|
||||||
|
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn it_solves_parta() {
|
fn it_solves_parta() {
|
||||||
|
@ -119,9 +151,9 @@ mod test {
|
||||||
let muls = parse_input_a(TEST_INPUT_A);
|
let muls = parse_input_a(TEST_INPUT_A);
|
||||||
|
|
||||||
assert_eq!(muls.len(), 4);
|
assert_eq!(muls.len(), 4);
|
||||||
assert_eq!(muls[0], Operation::Mult(Multiplication{ x: 2, y: 4 }));
|
assert_eq!(muls[0], Operation::Mult(Multiplication { x: 2, y: 4 }));
|
||||||
assert_eq!(muls[1], Operation::Mult(Multiplication{ x: 5, y: 5 }));
|
assert_eq!(muls[1], Operation::Mult(Multiplication { x: 5, y: 5 }));
|
||||||
assert_eq!(muls[2], Operation::Mult(Multiplication{ x: 11, y: 8 }));
|
assert_eq!(muls[2], Operation::Mult(Multiplication { x: 11, y: 8 }));
|
||||||
assert_eq!(muls[3], Operation::Mult(Multiplication{ x: 8, y: 5 }));
|
assert_eq!(muls[3], Operation::Mult(Multiplication { x: 8, y: 5 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue