2021: day07: use binary search for part 2
This commit is contained in:
parent
f621e603f3
commit
64ee9796ba
|
@ -87,28 +87,47 @@ fn part2(input: &str) -> Result<u64> {
|
||||||
let min = *horizontal_positions.iter().min().unwrap();
|
let min = *horizontal_positions.iter().min().unwrap();
|
||||||
let max = *horizontal_positions.iter().max().unwrap();
|
let max = *horizontal_positions.iter().max().unwrap();
|
||||||
|
|
||||||
let minimum_fuel = (min..=max)
|
let optimal_distance = minimize_binary_search(&horizontal_positions, min, max, part2_distance);
|
||||||
.map(|pos| {
|
let minimum_fuel = horizontal_positions
|
||||||
horizontal_positions
|
.iter()
|
||||||
.iter()
|
.map(|n| part2_distance(*n, optimal_distance))
|
||||||
.map(|n| part2_distance(*n, pos))
|
.sum::<u64>();
|
||||||
.sum::<f64>()
|
|
||||||
.floor() as u64
|
|
||||||
})
|
|
||||||
.min()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Ok(minimum_fuel)
|
Ok(minimum_fuel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn minimize_binary_search<F>(positions: &[u64], min: u64, max: u64, distance: F) -> u64
|
||||||
|
where
|
||||||
|
F: Fn(u64, u64) -> u64,
|
||||||
|
{
|
||||||
|
if min == max {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mid1 = min + (max - min) / 2;
|
||||||
|
let mid2 = mid1 + 1;
|
||||||
|
|
||||||
|
let (cost1, cost2) = positions
|
||||||
|
.iter()
|
||||||
|
.map(|n| (distance(*n, mid1), distance(*n, mid2)))
|
||||||
|
.reduce(|(sum1, sum2), (x1, x2)| (sum1 + x1, sum2 + x2))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if cost1 < cost2 {
|
||||||
|
minimize_binary_search(positions, min, mid1, distance)
|
||||||
|
} else {
|
||||||
|
minimize_binary_search(positions, mid2, max, distance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn abs_diff(a: u64, b: u64) -> u64 {
|
fn abs_diff(a: u64, b: u64) -> u64 {
|
||||||
a.max(b) - a.min(b)
|
a.max(b) - a.min(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2_distance(a: u64, b: u64) -> f64 {
|
fn part2_distance(a: u64, b: u64) -> u64 {
|
||||||
let distance = abs_diff(a, b) as f64;
|
let distance = abs_diff(a, b);
|
||||||
|
|
||||||
distance * (distance + 1.0) / 2.0
|
distance * (distance + 1) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in a new issue