diff --git a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs index 6de70e6..49066d1 100644 --- a/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs +++ b/aoc2021/aoc2021_bench/benches/aoc2021_bench.rs @@ -5,7 +5,6 @@ use aoc2021::day02; use aoc2021::day03; use aoc2021::day04; use aoc2021::day05; -use aoc2021::day06; fn aoc2021_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); @@ -13,7 +12,6 @@ fn aoc2021_all(c: &mut Criterion) { c.bench_function("day03", |b| b.iter(|| day03::run().unwrap())); c.bench_function("day04", |b| b.iter(|| day04::run().unwrap())); c.bench_function("day05", |b| b.iter(|| day05::run().unwrap())); - c.bench_function("day06", |b| b.iter(|| day06::run().unwrap())); } criterion_group! { diff --git a/aoc2021/input/day06_provided.txt b/aoc2021/input/day06_provided.txt deleted file mode 100644 index 55129f1..0000000 --- a/aoc2021/input/day06_provided.txt +++ /dev/null @@ -1 +0,0 @@ -3,4,3,1,2 diff --git a/aoc2021/src/day06.rs b/aoc2021/src/day06.rs index 3fae107..876252c 100644 --- a/aoc2021/src/day06.rs +++ b/aoc2021/src/day06.rs @@ -5,7 +5,7 @@ use anyhow::Result; const INPUT: &str = include_str!("../input/day06.txt"); -const SPAWNING_DELAY: usize = 7; +const SPAWNING_DELAY: u8 = 7; const TURNS_PART_1: usize = 80; const TURNS_PART_2: usize = 256; @@ -19,15 +19,63 @@ pub fn run() -> Result { } fn part1(input: &str) -> Result { - let mut school = input.trim().parse::()?; + let mut school = input + .trim() + .split(',') + .map(str::parse::) + .collect::>>()?; - Ok(school.grow_for(TURNS_PART_1)) + 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::()?; - Ok(school.grow_for(TURNS_PART_2)) + 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 { @@ -42,60 +90,37 @@ impl School { self.fish_timers[i - 1] = self.fish_timers[i]; } - self.fish_timers[SPAWNING_DELAY - 1] += newly_spawned; + 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() } - - fn grow_for(&mut self, turns: usize) -> usize { - for _ in 0..turns { - self.next_turn(); - } - - self.size() - } } impl std::str::FromStr for School { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - let mut fish_timers = [0usize; SPAWNING_DELAY + 2]; + let mut fish_timers = [0usize; SPAWNING_DELAY as usize + 2]; for fish in s.split(',').map(str::parse::) { - fish_timers[fish?] += 1; + let fish = fish?; + fish_timers[fish] += 1; } Ok(School { fish_timers }) } } -#[cfg(test)] -mod tests { - use super::*; +impl std::str::FromStr for LanternFish { + type Err = anyhow::Error; - const PROVIDED: &str = include_str!("../input/day06_provided.txt"); - - #[test] - fn part1_provided() { - assert_eq!(part1(PROVIDED).unwrap(), 5934); - } - - #[test] - fn part1_real() { - assert_eq!(part1(INPUT).unwrap(), 350149); - } - - #[test] - fn part2_provided() { - assert_eq!(part2(PROVIDED).unwrap(), 26984457539); - } - - #[test] - fn part2_real() { - assert_eq!(part2(INPUT).unwrap(), 1590327954513); + fn from_str(s: &str) -> Result { + Ok(LanternFish { timer: s.parse()? }) } } + +#[cfg(test)] +mod tests {}