implement day 6
This commit is contained in:
parent
10e53e648d
commit
b02d56254d
65
src/day_06/mod.rs
Normal file
65
src/day_06/mod.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use yap::IntoTokens;
|
||||
|
||||
mod model;
|
||||
mod parsing;
|
||||
|
||||
pub use model::{Fish, School, SmartSchool};
|
||||
pub use parsing::parse_school_of_fish;
|
||||
|
||||
#[aoc_generator(day6)]
|
||||
pub fn parse_input(input: &str) -> School {
|
||||
parse_school_of_fish(&mut input.into_tokens())
|
||||
}
|
||||
|
||||
#[aoc(day6, part1)]
|
||||
pub fn part1(input: &School) -> usize {
|
||||
let mut school = input.clone();
|
||||
for _ in 0..80 {
|
||||
school.tick()
|
||||
}
|
||||
school.size()
|
||||
}
|
||||
|
||||
#[aoc(day6, part1, smart_school)]
|
||||
pub fn part1_smart(input: &School) -> usize {
|
||||
let mut school = SmartSchool::from(input);
|
||||
for _ in 0..80 {
|
||||
school.tick()
|
||||
}
|
||||
school.size()
|
||||
}
|
||||
|
||||
#[aoc(day6, part2)]
|
||||
pub fn part2(input: &School) -> usize {
|
||||
let mut school = SmartSchool::from(input);
|
||||
for _ in 0..256 {
|
||||
school.tick()
|
||||
}
|
||||
school.size()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
const EXAMPLE_INPUT: &str = "3,4,3,1,2";
|
||||
const RESULT_PART_1: usize = 5934;
|
||||
const RESULT_PART_2: usize = 26_984_457_539;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let result = super::part1(&super::parse_input(EXAMPLE_INPUT));
|
||||
assert_eq!(result, RESULT_PART_1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let result = super::part2(&super::parse_input(EXAMPLE_INPUT));
|
||||
assert_eq!(result, RESULT_PART_2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_example() {
|
||||
let example = super::parse_input(EXAMPLE_INPUT);
|
||||
assert!(example.size() == 5);
|
||||
}
|
||||
}
|
119
src/day_06/model.rs
Normal file
119
src/day_06/model.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub struct Fish {
|
||||
pub timer: u8,
|
||||
}
|
||||
|
||||
impl Default for Fish {
|
||||
fn default() -> Fish {
|
||||
Fish::new(8)
|
||||
}
|
||||
}
|
||||
|
||||
impl Fish {
|
||||
fn tick(&mut self) -> Option<Fish> {
|
||||
match self.timer {
|
||||
0 => {
|
||||
self.timer = 6;
|
||||
Some(Fish::default())
|
||||
}
|
||||
_ => {
|
||||
self.timer -= 1;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new(timer: u8) -> Fish {
|
||||
Fish { timer }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Default)]
|
||||
pub struct School {
|
||||
pub fishes: Vec<Fish>,
|
||||
}
|
||||
|
||||
impl School {
|
||||
pub fn tick(&mut self) {
|
||||
let mut spawned = Vec::new();
|
||||
for fish in self.fishes.iter_mut() {
|
||||
if let Some(fish) = fish.tick() {
|
||||
spawned.push(fish);
|
||||
}
|
||||
}
|
||||
self.fishes.append(&mut spawned);
|
||||
}
|
||||
|
||||
pub fn add(&mut self, fish: Fish) {
|
||||
self.fishes.push(fish);
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.fishes.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Default)]
|
||||
pub struct SmartSchool {
|
||||
pub fish_counter: [usize; 9],
|
||||
}
|
||||
|
||||
impl SmartSchool {
|
||||
pub fn tick(&mut self) {
|
||||
let new_fish = self.fish_counter[0];
|
||||
for i in 1..self.fish_counter.len() {
|
||||
self.fish_counter[i - 1] = self.fish_counter[i];
|
||||
}
|
||||
self.fish_counter[8] = new_fish;
|
||||
self.fish_counter[6] += new_fish;
|
||||
}
|
||||
|
||||
pub fn add(&mut self, fish: Fish) {
|
||||
self.fish_counter[fish.timer as usize] += 1;
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.fish_counter.iter().sum()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&School> for SmartSchool {
|
||||
fn from(school: &School) -> Self {
|
||||
let mut smart = SmartSchool::default();
|
||||
for fish in &school.fishes {
|
||||
smart.add(*fish);
|
||||
}
|
||||
smart
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Fish, School};
|
||||
|
||||
#[test]
|
||||
fn default() {
|
||||
assert_eq!(Fish::default().timer, 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn() {
|
||||
let mut fish = Fish::default();
|
||||
for _ in 0..8 {
|
||||
assert_eq!(fish.tick(), None);
|
||||
}
|
||||
assert_eq!(fish.tick(), Some(Fish::default()));
|
||||
assert_eq!(fish.timer, 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn school_growth() {
|
||||
let mut school = School::default();
|
||||
school.add(Fish::new(0));
|
||||
school.add(Fish::new(0));
|
||||
school.add(Fish::new(0));
|
||||
assert_eq!(school.size(), 3);
|
||||
school.tick();
|
||||
assert_eq!(school.size(), 6);
|
||||
}
|
||||
}
|
35
src/day_06/parsing.rs
Normal file
35
src/day_06/parsing.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
use super::model::{Fish, School};
|
||||
use crate::parsing::parse_number;
|
||||
use yap::Tokens;
|
||||
|
||||
pub fn parse_fish(tokens: &mut impl Tokens<Item = char>) -> Option<Fish> {
|
||||
parse_number(tokens).map(|num| Fish { timer: num })
|
||||
}
|
||||
|
||||
pub fn parse_school_of_fish(tokens: &mut impl Tokens<Item = char>) -> School {
|
||||
School {
|
||||
fishes: tokens.sep_by(|t| parse_fish(t), |t| t.token(',')).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::model::Fish;
|
||||
use yap::IntoTokens;
|
||||
|
||||
#[test]
|
||||
fn parse_fish() {
|
||||
assert_eq!(
|
||||
Some(Fish { timer: 1 }),
|
||||
super::parse_fish(&mut "1".into_tokens())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_school() {
|
||||
assert_eq!(
|
||||
5,
|
||||
super::parse_school_of_fish(&mut "3,4,3,1,2".into_tokens()).size()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,5 +7,6 @@ pub mod day_02;
|
|||
pub mod day_03;
|
||||
pub mod day_04;
|
||||
pub mod day_05;
|
||||
pub mod day_06;
|
||||
|
||||
aoc_lib! { year = 2021 }
|
||||
|
|
Loading…
Reference in a new issue