implement day 6

This commit is contained in:
Jan Christian Grünhage 2021-12-07 09:51:26 +01:00
parent 10e53e648d
commit b02d56254d
4 changed files with 220 additions and 0 deletions

65
src/day_06/mod.rs Normal file
View 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
View 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
View 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()
);
}
}

View file

@ -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 }