diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2021-12-02 09:19:49 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2021-12-02 09:19:49 +0200 |
commit | e023b2ad45e8eb624b15a9301a3a96fbb9442e92 (patch) | |
tree | 7d13c3f75d008cfe09e943b778712021b1948a7a /src/bin/day_2_part_2.rs | |
parent | e132e55fee2822f6eeb1e47a69491e69b22bb41f (diff) |
Day 2
Diffstat (limited to 'src/bin/day_2_part_2.rs')
-rw-r--r-- | src/bin/day_2_part_2.rs | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/bin/day_2_part_2.rs b/src/bin/day_2_part_2.rs new file mode 100644 index 0000000..de5b334 --- /dev/null +++ b/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) +} |