1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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)
}
|