summaryrefslogtreecommitdiff
path: root/2021/src/bin/day_6.rs
diff options
context:
space:
mode:
Diffstat (limited to '2021/src/bin/day_6.rs')
-rw-r--r--2021/src/bin/day_6.rs79
1 files changed, 79 insertions, 0 deletions
diff --git a/2021/src/bin/day_6.rs b/2021/src/bin/day_6.rs
new file mode 100644
index 0000000..9a40f9e
--- /dev/null
+++ b/2021/src/bin/day_6.rs
@@ -0,0 +1,79 @@
+use nom::{
+ bytes::complete::tag,
+ character::complete::u32 as nom_u32,
+ combinator::{map, map_res},
+ multi::separated_list1,
+ IResult, ToUsize,
+};
+use std::{collections::VecDeque, fs};
+use thiserror::Error;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_6.txt")?;
+ let mut swarm = parse_swarm(&input).unwrap().1;
+ for _ in 0..80 {
+ swarm.grow();
+ }
+ dbg!(swarm.fish_sum());
+
+ for _ in 80..256 {
+ swarm.grow();
+ }
+ dbg!(swarm.fish_sum());
+
+ Ok(())
+}
+
+#[derive(
+ Default, Debug, Clone, Copy, derive_more::Add, derive_more::AddAssign, derive_more::Sum,
+)]
+struct FishCount(u64);
+
+const FISH_INITIAL_SPAWN_COUNTDOWN: usize = 9;
+const FISH_REPEAT_SPAWN_COUNTDOWN: usize = 7;
+#[derive(Debug)]
+struct Swarm {
+ fish: VecDeque<FishCount>,
+}
+
+#[derive(Debug, Error)]
+enum SwarmParseError {
+ #[error("input was out of range")]
+ OutOfRange,
+}
+
+impl Swarm {
+ fn new(fish_counters: Vec<usize>) -> Result<Swarm, SwarmParseError> {
+ let mut fish = VecDeque::with_capacity(FISH_INITIAL_SPAWN_COUNTDOWN);
+ for _ in 0..FISH_INITIAL_SPAWN_COUNTDOWN {
+ fish.push_back(FishCount::default());
+ }
+ for fish_counter in fish_counters {
+ if fish_counter > fish.len() {
+ return Err(SwarmParseError::OutOfRange);
+ }
+ fish[fish_counter] += FishCount(1);
+ }
+ Ok(Swarm { fish })
+ }
+
+ fn grow(&mut self) {
+ let spawning = self
+ .fish
+ .pop_front()
+ .expect("Fish buffer should maintain exactly 9 entries");
+ self.fish[FISH_REPEAT_SPAWN_COUNTDOWN - 1] += spawning;
+ self.fish.push_back(spawning);
+ }
+
+ fn fish_sum(&self) -> FishCount {
+ self.fish.iter().copied().sum()
+ }
+}
+
+fn parse_swarm(input: &str) -> IResult<&str, Swarm> {
+ map_res(
+ separated_list1(tag(","), map(nom_u32, |n| n.to_usize())),
+ Swarm::new,
+ )(input)
+}