diff --git a/2023/day6/rust/src/main.rs b/2023/day6/rust/src/main.rs index 36cbcf3..f224132 100644 --- a/2023/day6/rust/src/main.rs +++ b/2023/day6/rust/src/main.rs @@ -1,6 +1,16 @@ #![warn(clippy::pedantic)] -use std::io::stdin; +use std::{io::stdin, ops::Div}; + +#[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_precision_loss +)] +// FIXME: https://github.com/rust-lang/rust/issues/116226 +fn isqrt(n: u64) -> u64 { + (n as f64).sqrt().floor() as u64 +} fn calculate_score>(races: I) -> u64 { races @@ -11,16 +21,14 @@ fn calculate_score>(races: I) -> u64 { // x^2-tx+r = 0 // [ x^2+px+q = 0 ==> x = -p/2±sqrt((p/2)^2-q) ] // x = t/2 ± sqrt(t^2/4-r) + // x = (t ± 2 * sqrt(t^2/4-r)) / 2 + // x = (t ± sqrt(t^2-4r)) / 2 - #[allow(clippy::cast_precision_loss)] - let t = t as f64; - #[allow(clippy::cast_precision_loss)] - let r = r as f64; - - let v = t / 2.0; - let w = (t.powi(2) / 4.0 - r).sqrt(); - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - ((v - w + 1.0).floor() as u64, (v + w - 1.0).ceil() as u64) + let d_squared = t.pow(2) - 4 * r; + // add a little bias for perfect squares, and subtract 1 to get the x values that lie + // inside r + let d = isqrt(d_squared - 1) - 1; + ((t - d).div(2), (t + d).div_ceil(2)) }) .map(|(min, max)| max - min + 1) .product()