mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 12:50:32 +01:00
Use math instead of binary search
This commit is contained in:
@@ -19,7 +19,11 @@ fn solve_quadratic(a: f64, b: f64, c: f64) -> Option<f64> {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// Don't care about the smaller solution due to problem statement
|
// Don't care about the smaller solution due to problem statement
|
||||||
Some((-b - d.sqrt()) / 2. / a)
|
if a > 0. {
|
||||||
|
Some((-b + d.sqrt()) / 2. / a)
|
||||||
|
} else {
|
||||||
|
Some((-b - d.sqrt()) / 2. / a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,37 +64,27 @@ fn find_hit(initial: i32, range: &RangeInclusive<i32>) -> Option<RangeInclusive<
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn find_speed(x: i32, range: &RangeInclusive<i32>) -> Option<RangeInclusive<i32>> {
|
fn find_speed(x: i32, range: &RangeInclusive<i32>) -> Option<RangeInclusive<i32>> {
|
||||||
let mut min = 0;
|
if *range.end() <= position(x, x) {
|
||||||
let mut max = *range.end();
|
// Can and should come to a full stop
|
||||||
|
let max = solve_quadratic(0.5, 0.5, -*range.end() as f64)? as i32;
|
||||||
|
|
||||||
// Need to tweak the formula as x slows down
|
let min = (0..=max)
|
||||||
let x_pos = |speed| position(speed, speed.min(x));
|
.rev()
|
||||||
|
.take_while(|&n| range.contains(&position(n, n)))
|
||||||
|
.last()?;
|
||||||
|
|
||||||
while max >= min {
|
Some(min..=max)
|
||||||
let speed = (max + min) / 2;
|
} else {
|
||||||
|
// Might hit the target at speed
|
||||||
|
let max = (x * x + 2 * *range.end() - x) / (2 * x);
|
||||||
|
|
||||||
let pos = x_pos(speed);
|
let min = (0..=max)
|
||||||
|
.rev()
|
||||||
|
.take_while(|&n| range.contains(&position(n, n.min(x))))
|
||||||
|
.last()?;
|
||||||
|
|
||||||
if range.contains(&x_pos(speed)) {
|
Some(min..=max)
|
||||||
let min_speed = (0..speed)
|
|
||||||
.rev()
|
|
||||||
.take_while(|&speed| range.contains(&x_pos(speed)))
|
|
||||||
.min()
|
|
||||||
.unwrap_or(speed);
|
|
||||||
|
|
||||||
let max_speed = ((speed + 1)..)
|
|
||||||
.take_while(|&speed| range.contains(&x_pos(speed)))
|
|
||||||
.max()
|
|
||||||
.unwrap_or(speed);
|
|
||||||
return Some(min_speed..=max_speed);
|
|
||||||
} else if pos < *range.start() {
|
|
||||||
min = speed + 1;
|
|
||||||
} else {
|
|
||||||
max = speed - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_range(input: &[u8]) -> IResult<&[u8], RangeInclusive<i32>> {
|
fn parse_range(input: &[u8]) -> IResult<&[u8], RangeInclusive<i32>> {
|
||||||
|
|||||||
Reference in New Issue
Block a user