Skip to content

Commit 75909cc

Browse files
committed
Day 03 solutiosn using nom
1 parent 486ed51 commit 75909cc

File tree

5 files changed

+151
-4
lines changed

5 files changed

+151
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,4 @@ This should start the server at `localhost:8080`.
8888

8989
❄️ [Day 01](aoc-solver/src/y2024/day01.rs)
9090
❄️ [Day 02](aoc-solver/src/y2024/day02.rs)
91+
❄️ [Day 03](aoc-solver/src/y2024/day03.rs)

aoc-solver/src/y2024/day03.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use nom::{
2+
branch::alt,
3+
bytes::complete::tag,
4+
character::complete::{anychar, char, digit1},
5+
combinator::{map, map_res},
6+
multi::many0,
7+
sequence::{delimited, preceded, separated_pair},
8+
IResult,
9+
};
10+
11+
use crate::solution::{AocError, Solution};
12+
13+
#[derive(PartialEq, Debug)]
14+
enum Instruction {
15+
Mul(u32, u32),
16+
Enable,
17+
Disable,
18+
}
19+
20+
fn parse_mul(input: &str) -> IResult<&str, (u32, u32)> {
21+
preceded(
22+
tag("mul"),
23+
delimited(
24+
char('('),
25+
separated_pair(
26+
map_res(digit1, |i: &str| i.parse::<u32>()),
27+
char(','),
28+
map_res(digit1, |i: &str| i.parse::<u32>()),
29+
),
30+
char(')'),
31+
),
32+
)(input)
33+
}
34+
35+
fn parse_other(input: &str) -> IResult<&str, ()> {
36+
let (unhandled, _ignored) = anychar(input)?;
37+
Ok((unhandled, ()))
38+
}
39+
40+
fn parse_instruction(input: &str) -> IResult<&str, Option<Instruction>> {
41+
alt((
42+
map(tag("do()"), |_| Some(Instruction::Enable)),
43+
map(tag("don't()"), |_| Some(Instruction::Disable)),
44+
map(parse_mul, |(a, b)| Some(Instruction::Mul(a, b))),
45+
map(parse_other, |_| None),
46+
))(input)
47+
}
48+
49+
fn parse(input: &str) -> Result<Vec<Instruction>, AocError> {
50+
let (_unhandled, parsed) =
51+
many0(parse_instruction)(input).map_err(|err| AocError::parse(input, err))?;
52+
53+
let instructions = parsed.into_iter().flatten().collect();
54+
55+
Ok(instructions)
56+
}
57+
58+
pub struct Day03;
59+
impl Solution for Day03 {
60+
type A = u32;
61+
type B = u32;
62+
63+
fn default_input(&self) -> &'static str {
64+
include_str!("../../../inputs/2024/day03.txt")
65+
}
66+
67+
fn part_1(&self, input: &str) -> Result<u32, AocError> {
68+
let sum = parse(input)?
69+
.iter()
70+
.map(|instruction| match instruction {
71+
Instruction::Mul(a, b) => a * b,
72+
_ => 0,
73+
})
74+
.sum();
75+
76+
Ok(sum)
77+
}
78+
79+
fn part_2(&self, input: &str) -> Result<u32, AocError> {
80+
let mut enabled = true;
81+
let sum = parse(input)?
82+
.iter()
83+
.map(|instruction| match instruction {
84+
Instruction::Mul(a, b) if enabled => a * b,
85+
Instruction::Enable => {
86+
enabled = true;
87+
0
88+
}
89+
Instruction::Disable => {
90+
enabled = false;
91+
0
92+
}
93+
_ => 0,
94+
})
95+
.sum();
96+
97+
Ok(sum)
98+
}
99+
}
100+
101+
#[cfg(test)]
102+
mod tests {
103+
use super::*;
104+
105+
#[test]
106+
fn it_solves_part1_example() {
107+
assert_eq!(
108+
Day03.part_1(
109+
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"
110+
),
111+
Ok(161)
112+
);
113+
}
114+
115+
#[test]
116+
fn it_solves_part2_example() {
117+
assert_eq!(
118+
Day03.part_2(
119+
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"
120+
),
121+
Ok(48)
122+
);
123+
}
124+
125+
#[test]
126+
fn it_parses_input() {
127+
assert_eq!(
128+
parse("xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"),
129+
Ok(vec![
130+
Instruction::Mul(2, 4),
131+
Instruction::Disable,
132+
Instruction::Mul(5, 5),
133+
Instruction::Mul(11, 8),
134+
Instruction::Enable,
135+
Instruction::Mul(8, 5),
136+
])
137+
);
138+
}
139+
}

aoc-solver/src/y2024/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::solution::{Solution, Solver};
22

33
pub mod day01;
44
pub mod day02;
5-
// pub mod day03;
5+
pub mod day03;
66
// pub mod day04;
77
// pub mod day05;
88
// pub mod day06;
@@ -26,7 +26,7 @@ pub mod day02;
2626
// pub mod day24;
2727
// pub mod day25;
2828

29-
pub const MAX_DAYS: u8 = 2;
29+
pub const MAX_DAYS: u8 = 3;
3030

3131
pub struct Y2024;
3232

@@ -35,7 +35,7 @@ impl Solver for Y2024 {
3535
match day {
3636
1 => day01::Day01.run(input, 1, 2024),
3737
2 => day02::Day02.run(input, 2, 2024),
38-
// 3 => day03::Day03.run(input, 3, 2024),
38+
3 => day03::Day03.run(input, 3, 2024),
3939
// 4 => day04::Day04.run(input, 4, 2024),
4040
// 5 => day05::Day05.run(input, 5, 2024),
4141
// 6 => day06::Day06.run(input, 6, 2024),
@@ -77,7 +77,7 @@ impl Solver for Y2024 {
7777
match day {
7878
1 => include_str!("./day01.rs"),
7979
2 => include_str!("./day02.rs"),
80-
// 3 => include_str!("./day03.rs"),
80+
3 => include_str!("./day03.rs"),
8181
// 4 => include_str!("./day04.rs"),
8282
// 5 => include_str!("./day05.rs"),
8383
// 6 => include_str!("./day06.rs"),

aoc-web/src/header.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub fn header(props: &HeaderProps) -> Html {
2121
<>
2222
<NavLink route={Route::Solution { year: 2024, day: 1 }} current={props.route.clone()} text={"1"}/>
2323
<NavLink route={Route::Solution { year: 2024, day: 2 }} current={props.route.clone()} text={"2"}/>
24+
<NavLink route={Route::Solution { year: 2024, day: 3 }} current={props.route.clone()} text={"3"}/>
2425
</>
2526
}
2627
},

0 commit comments

Comments
 (0)