diff --git a/aoc2021/src/day07.rs b/aoc2021/src/day07.rs index 861208e..764df93 100644 --- a/aoc2021/src/day07.rs +++ b/aoc2021/src/day07.rs @@ -8,6 +8,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -26,10 +27,44 @@ fn part1(input: &str) -> Result { Ok(horizontal_positions .iter() // TODO: use abs_diff when stabilized - .map(|n| n.max(&median) - n.min(&median)) + .map(|n| abs_diff(*n, median)) .sum()) } +fn part2(input: &str) -> Result { + let horizontal_positions = input + .trim() + .split(',') + .map(|n| n.parse::().context("couldn't parse position")) + .collect::>>()?; + + let min = *horizontal_positions.iter().min().unwrap(); + let max = *horizontal_positions.iter().max().unwrap(); + + let minimum_fuel = (min..=max) + .map(|pos| { + horizontal_positions + .iter() + .map(|n| part2_distance(*n, pos)) + .sum::() + .floor() as u64 + }) + .min() + .unwrap(); + + Ok(minimum_fuel) +} + +fn abs_diff(a: u64, b: u64) -> u64 { + a.max(b) - a.min(b) +} + +fn part2_distance(a: u64, b: u64) -> f64 { + let distance = abs_diff(a, b) as f64; + + distance * (distance + 1.0) / 2.0 +} + #[cfg(test)] mod tests { use super::*; @@ -45,4 +80,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 340056); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 168); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 96592275); + } }