diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/day1.rs | 45 | ||||
-rw-r--r-- | src/day2.rs | 137 | ||||
-rw-r--r-- | src/lib.rs | 1 |
5 files changed, 187 insertions, 1 deletions
@@ -1,5 +1,7 @@ /target *~ +/input +*.swp # Added by cargo # @@ -8,3 +8,6 @@ edition = "2021" [dependencies] aoc-runner = "0.3" aoc-runner-derive = "0.3" + +[profile.dev] +opt-level=3 diff --git a/src/day1.rs b/src/day1.rs index e5dd408..1326af6 100644 --- a/src/day1.rs +++ b/src/day1.rs @@ -6,7 +6,7 @@ pub fn input_generator<'c>(input : &'c str) -> Vec<u32>{ input.lines().map(u32::from_str).map(Result::unwrap).collect() } -#[aoc(day1, part1)] +#[aoc(day1, part1, InternalState)] pub fn solve_part1(input : &Vec<u32>) -> u32 { struct Helper { count : u32, @@ -14,3 +14,46 @@ pub fn solve_part1(input : &Vec<u32>) -> u32 { } input.iter().fold(Helper{count:0,prev:u32::MAX},|x ,curr| -> Helper {if curr > &x.prev {Helper{count : x.count + 1, prev : *curr}} else {Helper{count : x.count, prev : *curr}}}).count } + +#[aoc(day1, part1, Iterators)] +pub fn solve_part1_iterators(input : &Vec<u32>) -> usize { + input.iter().skip(1).zip(input.iter()).filter(|(new, old)| new > old).count() +} + +#[aoc(day1, part2, InternalState)] +pub fn solve_part2(input : &Vec<u32>) -> usize { + let floating_window :u32 = input.iter().take(3).sum(); + input.iter().skip(3).zip(input.iter()).scan(floating_window, |floating_window, (new, old)| { + let prev_window = *floating_window; + *floating_window = (*floating_window + *new) - *old; + Some((*floating_window, prev_window)) + }).filter(|(new, old)| new > old).count() +} + +#[aoc(day1,part2, DumbLoop)] +pub fn solve_part2_dumb_loop(input : &Vec<u32>) -> usize { + if input.len() < 3 { + 0 + } + else { + let mut floating_window = input[0]+input[1]+input[2]; + let mut sum = 0; + for index in 3..input.len() { + let old = floating_window; + floating_window = (floating_window + input[index]) - input[index -3]; + if floating_window > old { + sum = sum + 1; + } + } + sum + } +} + +#[aoc(day1, part2, Iterators)] +pub fn solve_part2_iterators(input : &Vec<u32>) -> usize { + let sliding_window = input.iter().skip(2).zip(input.iter().skip(1)).zip(input.iter()) + .map(|((third, second), first)| third + second + first); + let old_window = sliding_window.clone(); + let sliding_window = sliding_window.skip(1); + sliding_window.zip(old_window).filter(|(new, old)| new > old).count() +} diff --git a/src/day2.rs b/src/day2.rs new file mode 100644 index 0000000..c821d07 --- /dev/null +++ b/src/day2.rs @@ -0,0 +1,137 @@ +use aoc_runner_derive::*; +use std::str::FromStr; +use std::error::Error; +use std::ops::Add; +use std::iter::Sum; + +enum Direction { + Forward, + Up, + Down, + Back, +} + +pub struct Command { + direction : Direction, + amount : u32 +} + +#[derive(Debug)] +pub struct CommandError(String); +impl std::fmt::Display for CommandError { + fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + write!(f,"Invalid Input: {}",self.0) + } +} +impl Error for CommandError {} + +struct Movement { + x : i32, + y : i32, +} + +impl Add for Movement{ + type Output = Movement; + fn add(self, other : Movement) -> Movement { + Movement{x : self.x + other.x, y : self.y + other.y} + } +} + +impl Sum for Movement{ + fn sum<I: Iterator<Item=Self>>(iter: I) -> Self { + iter.fold(Movement{x:0,y:0},|x,y| x+y) + } +} + +impl From<&Command> for Movement { + fn from(c: &Command) -> Self { + match c.direction { + Direction::Forward => { Movement{x : c.amount as i32, y : 0} } + Direction::Up => { Movement{x : 0, y : -(c.amount as i32)}} + Direction::Down => { Movement{x :0, y : c.amount as i32}} + Direction::Back => { Movement{x : -(c.amount as i32), y : 0} } + } + } +} + +enum ReinterpretedCommand { + Move(i32), + ChangeAim(i32), +} + +impl From<&Command> for ReinterpretedCommand { + fn from(c: &Command) -> Self { + match c.direction { + Direction::Forward => { ReinterpretedCommand::Move(c.amount as i32)} + Direction::Up => { ReinterpretedCommand::ChangeAim(-(c.amount as i32))} + Direction::Down => { ReinterpretedCommand::ChangeAim(c.amount as i32)} + Direction::Back => {ReinterpretedCommand::Move(-(c.amount as i32))} + } + } +} + +struct MovementWithDirection { + x : i32, + y : i32, + aim : i32, +} + +impl Add<ReinterpretedCommand> for MovementWithDirection { + type Output = Self; + fn add(self, command : ReinterpretedCommand) -> Self { + match command { + ReinterpretedCommand::Move(distance) => { + MovementWithDirection{ + x: self.x + distance, + y: self.y + self.aim * distance, + aim : self.aim, + } + } + ReinterpretedCommand::ChangeAim(delta) => { + MovementWithDirection { + x: self.x, + y: self.y, + aim : self.aim + delta, + } + } + } + } +} + +impl FromStr for Command { + type Err = CommandError; + fn from_str(s: &str) -> Result<Self, CommandError> { + let mut parts = s.split(" "); + let direction = match parts.next() { + Some("down") => { Some(Direction::Down) } + Some("up") => { Some(Direction::Up) } + Some("forward") => { Some(Direction::Forward) } + Some("back") => { Some(Direction::Back) } + None | Some(_) => { None } + }; + let amount = parts.next().map(|ss| FromStr::from_str(ss).ok()).flatten(); + direction.zip(amount) + .map(|(direction, amount)| Command{direction,amount}) + .ok_or_else(||{ CommandError(String::from(s)) }) + } +} + +#[aoc_generator(day2)] +pub fn input_generator<'c>(input : &'c str) -> Vec<Command>{ + input.lines().map(Command::from_str).map(Result::unwrap).collect() +} + +#[aoc(day2, part1)] +pub fn solve_part1(input : &Vec<Command>) -> i32 { + let target : Movement = input.iter().map(From::from).sum(); + target.x*target.y +} + +#[aoc(day2, part2)] +pub fn solve_part2(input : &Vec<Command>) -> i32 { + let target = input.iter() + .map(From::from) + .fold(MovementWithDirection{x:0,y:0,aim:0},Add::add); + target.x*target.y +} + @@ -1,5 +1,6 @@ use aoc_runner_derive::aoc_lib; pub mod day1; +pub mod day2; aoc_lib!{ year = 2021 } |