diff --git a/day-6/benches/bench.rs b/day-6/benches/bench.rs index aa945d1..eb909f5 100644 --- a/day-6/benches/bench.rs +++ b/day-6/benches/bench.rs @@ -1,5 +1,9 @@ #![allow(dead_code)] +// uncomment for unstable version +// #![allow(unused_attributes, incomplete_features)] +// #![feature(generic_const_exprs, const_for, const_mut_refs)] + use aoc_lib::AdventOfCode; use criterion::{black_box, criterion_group, criterion_main, Criterion}; diff --git a/day-6/src/main_unstable.rs b/day-6/src/main_unstable.rs new file mode 100644 index 0000000..8f4a096 --- /dev/null +++ b/day-6/src/main_unstable.rs @@ -0,0 +1,154 @@ +#![feature(generic_const_exprs)] +#![feature(const_for)] +#![feature(const_mut_refs)] + +use aoc_lib::*; + +aoc_setup!(Day6, sample 1: 5934, sample 2: 26984457539, part 1: 360268); + +pub struct Day6; + +impl AdventOfCode for Day6 { + type Input = Vec; // can be u8 + type Output = u64; + + fn parse_input(s: &str) -> Self::Input { + s.split(',').map(|l| l.parse().unwrap()).collect() + } + + fn solve_1(input: &Self::Input) -> Self::Output { + solve_smart::<80>(input) + } + + fn solve_2(input: &Self::Input) -> Self::Output { + solve_smart::<256>(input) + } +} + +pub fn solve_naive(input: &[usize]) -> u64 { + let mut vec: Vec = input.iter().copied().collect(); + + for _day in 0..DAYS { + let start_len = vec.len(); + for i in 0..start_len { + if vec[i] == 0 { + vec[i] = 6; + vec.push(8); + } else { + vec[i] -= 1; + } + } + } + + vec.len() as u64 +} + +pub fn solve_smart(input: &[usize]) -> u64 +where + [(); DAYS + 8]: Sized, +{ + let map = generate_map::(); + // println!("map: {:?}", map); + + // for every starting fish, calculate the amount of offspring they generate + let birthed_offspring: u64 = input + .iter() + .map(|&fish| (map[8 - fish + DAYS])) // lower number means born earlier, means more fish + .sum(); + + birthed_offspring // + (input.len() as u64) +} + +const fn generate_map() -> [u64; LEN + 8] +where + [(); LEN + 8]: Sized, +{ + // this map contains the number of offspring that are resultant from a fish born at time 0 + let mut map = [0u64; LEN + 8]; + + let mut day = 0; + loop { + let added_fish = get_fish_count_from_map_day(&map, day); + map[day] = added_fish; + // println!("day: {}, added_fish: {}", day, added_fish); + + day += 1; + + if day >= LEN + 8 { + break; + } + } + + map +} + +// rename me +// also const I think +const fn get_fish_count_from_map_day(map: &[u64], day: usize) -> u64 { + // always start with 1 fish + let mut added_fish = 1; + + // look at all days that spawn a fish, see how many fish result from this day + // can't use ranges in const fn yet + let mut offspring_day = 9; + + loop { + if day < offspring_day { + break; + } + + let remaining_days = day - offspring_day; + added_fish += map[remaining_days]; + + offspring_day += 7; + + if offspring_day > day { + break; + } + } + + added_fish +} + +#[test] +pub fn test_map() { + let map = generate_map::<{ 30 - 8 }>(); + + assert_eq!( + map, + [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 5, 5, 7, 7, 8, 8, + 8 + ] + ); +} + +#[test] +pub fn test_solve_naive() { + assert_eq!(5, solve_naive::<1>(&[3, 4, 3, 1, 2])); + assert_eq!(6, solve_naive::<2>(&[3, 4, 3, 1, 2])); + assert_eq!(7, solve_naive::<3>(&[3, 4, 3, 1, 2])); + assert_eq!(9, solve_naive::<4>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_naive::<5>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_naive::<6>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_naive::<7>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_naive::<8>(&[3, 4, 3, 1, 2])); + assert_eq!(11, solve_naive::<9>(&[3, 4, 3, 1, 2])); + assert_eq!(12, solve_naive::<10>(&[3, 4, 3, 1, 2])); + assert_eq!(15, solve_naive::<11>(&[3, 4, 3, 1, 2])); +} + +#[test] +pub fn test_solve_smart() { + assert_eq!(5, solve_smart::<1>(&[3, 4, 3, 1, 2])); + assert_eq!(6, solve_smart::<2>(&[3, 4, 3, 1, 2])); + assert_eq!(7, solve_smart::<3>(&[3, 4, 3, 1, 2])); + assert_eq!(9, solve_smart::<4>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_smart::<5>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_smart::<6>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_smart::<7>(&[3, 4, 3, 1, 2])); + assert_eq!(10, solve_smart::<8>(&[3, 4, 3, 1, 2])); + assert_eq!(11, solve_smart::<9>(&[3, 4, 3, 1, 2])); // fails + assert_eq!(12, solve_smart::<10>(&[3, 4, 3, 1, 2])); + assert_eq!(15, solve_smart::<11>(&[3, 4, 3, 1, 2])); +}