summaryrefslogtreecommitdiff
path: root/2021/src/bin/day_2_part_2.rs
diff options
context:
space:
mode:
Diffstat (limited to '2021/src/bin/day_2_part_2.rs')
-rw-r--r--2021/src/bin/day_2_part_2.rs124
1 files changed, 124 insertions, 0 deletions
diff --git a/2021/src/bin/day_2_part_2.rs b/2021/src/bin/day_2_part_2.rs
new file mode 100644
index 0000000..de5b334
--- /dev/null
+++ b/2021/src/bin/day_2_part_2.rs
@@ -0,0 +1,124 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{i64 as nom_i64, line_ending, space1},
+ combinator::map,
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_2.txt")?;
+ let route = parse_route(&input).unwrap().1;
+
+ let mut position = Position::default();
+ for instruction in &route {
+ position.advance(&instruction);
+ }
+ dbg!(position.horizontal.0 * position.depth.0);
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct Route(Vec<Instruction>);
+
+impl<'a> IntoIterator for &'a Route {
+ type Item = &'a Instruction;
+ type IntoIter = std::slice::Iter<'a, Instruction>;
+ fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
+ self.0.iter()
+ }
+}
+
+#[derive(Debug)]
+enum Instruction {
+ Forward(Distance),
+ Up(Aim),
+ Down(Aim),
+}
+
+#[derive(
+ Default,
+ Debug,
+ Clone,
+ Copy,
+ derive_more::Add,
+ derive_more::AddAssign,
+ derive_more::Sub,
+ derive_more::SubAssign,
+)]
+struct Distance(i64);
+#[derive(
+ Default,
+ Debug,
+ Clone,
+ Copy,
+ derive_more::Add,
+ derive_more::AddAssign,
+ derive_more::Sub,
+ derive_more::SubAssign,
+)]
+struct Aim(i64);
+
+impl std::ops::Mul<Distance> for Aim {
+ type Output = Distance;
+ fn mul(self, other: Distance) -> Distance {
+ Distance(self.0 * other.0)
+ }
+}
+
+#[derive(Default, Debug)]
+struct Position {
+ horizontal: Distance,
+ depth: Distance,
+ aim: Aim,
+}
+
+impl Position {
+ fn advance(&mut self, instruction: &Instruction) {
+ match instruction {
+ Instruction::Forward(distance) => {
+ self.horizontal += *distance;
+ self.depth += self.aim * *distance;
+ }
+ Instruction::Down(aim) => self.aim += *aim,
+ Instruction::Up(aim) => self.aim -= *aim,
+ }
+ }
+}
+
+fn parse_route(input: &str) -> IResult<&str, Route> {
+ map(separated_list1(line_ending, parse_instruction), Route)(input)
+}
+
+fn parse_instruction(input: &str) -> IResult<&str, Instruction> {
+ alt((parse_forward, parse_up, parse_down))(input)
+}
+
+fn parse_forward(input: &str) -> IResult<&str, Instruction> {
+ map(
+ tuple((tag("forward"), space1, parse_distance)),
+ |(_, _, distance)| Instruction::Forward(distance),
+ )(input)
+}
+fn parse_up(input: &str) -> IResult<&str, Instruction> {
+ map(tuple((tag("up"), space1, parse_aim)), |(_, _, aim)| {
+ Instruction::Up(aim)
+ })(input)
+}
+fn parse_down(input: &str) -> IResult<&str, Instruction> {
+ map(tuple((tag("down"), space1, parse_aim)), |(_, _, aim)| {
+ Instruction::Down(aim)
+ })(input)
+}
+
+fn parse_distance(input: &str) -> IResult<&str, Distance> {
+ map(nom_i64, Distance)(input)
+}
+
+fn parse_aim(input: &str) -> IResult<&str, Aim> {
+ map(nom_i64, Aim)(input)
+}