diff --git a/aoc2021/input/day06.txt b/aoc2021/input/day06.txt new file mode 100644 index 0000000..156bc49 --- /dev/null +++ b/aoc2021/input/day06.txt @@ -0,0 +1 @@ +4,1,4,1,3,3,1,4,3,3,2,1,1,3,5,1,3,5,2,5,1,5,5,1,3,2,5,3,1,3,4,2,3,2,3,3,2,1,5,4,1,1,1,2,1,4,4,4,2,1,2,1,5,1,5,1,2,1,4,4,5,3,3,4,1,4,4,2,1,4,4,3,5,2,5,4,1,5,1,1,1,4,5,3,4,3,4,2,2,2,2,4,5,3,5,2,4,2,3,4,1,4,4,1,4,5,3,4,2,2,2,4,3,3,3,3,4,2,1,2,5,5,3,2,3,5,5,5,4,4,5,5,4,3,4,1,5,1,3,4,4,1,3,1,3,1,1,2,4,5,3,1,2,4,3,3,5,4,4,5,4,1,3,1,1,4,4,4,4,3,4,3,1,4,5,1,2,4,3,5,1,1,2,1,1,5,4,2,1,5,4,5,2,4,4,1,5,2,2,5,3,3,2,3,1,5,5,5,4,3,1,1,5,1,4,5,2,1,3,1,2,4,4,1,1,2,5,3,1,5,2,4,5,1,2,3,1,2,2,1,2,2,1,4,1,3,4,2,1,1,5,4,1,5,4,4,3,1,3,3,1,1,3,3,4,2,3,4,2,3,1,4,1,5,3,1,1,5,3,2,3,5,1,3,1,1,3,5,1,5,1,1,3,1,1,1,1,3,3,1 diff --git a/aoc2021/src/day06.rs b/aoc2021/src/day06.rs new file mode 100644 index 0000000..876252c --- /dev/null +++ b/aoc2021/src/day06.rs @@ -0,0 +1,126 @@ +use std::fmt::Write; +use std::str; + +use anyhow::Result; + +const INPUT: &str = include_str!("../input/day06.txt"); + +const SPAWNING_DELAY: u8 = 7; +const TURNS_PART_1: usize = 80; +const TURNS_PART_2: usize = 256; + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut school = input + .trim() + .split(',') + .map(str::parse::) + .collect::>>()?; + + for _ in 0..TURNS_PART_1 { + let mut newly_spawned = 0; + + for fish in &mut school { + if fish.next_turn() { + newly_spawned += 1; + } + } + + school.resize_with(school.len() + newly_spawned, LanternFish::default) + } + + Ok(school.len()) +} + +fn part2(input: &str) -> Result { + let mut school = input.trim().parse::()?; + + for _ in 0..TURNS_PART_2 { + school.next_turn(); + } + + Ok(school.size()) +} + +struct LanternFish { + timer: u8, +} + +impl LanternFish { + fn spawn() -> Self { + LanternFish { + timer: SPAWNING_DELAY + 1, + } + } + + fn next_turn(&mut self) -> bool { + if self.timer == 0 { + self.timer = SPAWNING_DELAY - 1; + true + } else { + self.timer -= 1; + false + } + } +} + +impl Default for LanternFish { + fn default() -> Self { + Self::spawn() + } +} + +struct School { + fish_timers: [usize; SPAWNING_DELAY as usize + 2], +} + +impl School { + fn next_turn(&mut self) { + let newly_spawned = self.fish_timers[0]; + + for i in 1..self.fish_timers.len() { + self.fish_timers[i - 1] = self.fish_timers[i]; + } + + self.fish_timers[SPAWNING_DELAY as usize - 1] += newly_spawned; + *self.fish_timers.last_mut().unwrap() = newly_spawned; + } + + fn size(&self) -> usize { + self.fish_timers.iter().sum() + } +} + +impl std::str::FromStr for School { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut fish_timers = [0usize; SPAWNING_DELAY as usize + 2]; + + for fish in s.split(',').map(str::parse::) { + let fish = fish?; + fish_timers[fish] += 1; + } + + Ok(School { fish_timers }) + } +} + +impl std::str::FromStr for LanternFish { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(LanternFish { timer: s.parse()? }) + } +} + +#[cfg(test)] +mod tests {} diff --git a/aoc2021/src/lib.rs b/aoc2021/src/lib.rs index e0126f6..f236974 100644 --- a/aoc2021/src/lib.rs +++ b/aoc2021/src/lib.rs @@ -5,3 +5,4 @@ pub mod day02; pub mod day03; pub mod day04; pub mod day05; +pub mod day06; diff --git a/aoc2021/src/main.rs b/aoc2021/src/main.rs index 20a1ce0..c712420 100644 --- a/aoc2021/src/main.rs +++ b/aoc2021/src/main.rs @@ -7,9 +7,17 @@ use aoc2021::day02; use aoc2021::day03; use aoc2021::day04; use aoc2021::day05; +use aoc2021::day06; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run, day05::run]; + let days: &[DayFunc] = &[ + day01::run, + day02::run, + day03::run, + day04::run, + day05::run, + day06::run, + ]; aoc::run(days) }