From e94416addf2cb76624846b2bcaa00d3a683b6bf8 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 6 Dec 2023 11:17:00 +0100 Subject: [PATCH] Day06 - part 1 --- src/day06.rs | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 2 + 2 files changed, 134 insertions(+) create mode 100644 src/day06.rs diff --git a/src/day06.rs b/src/day06.rs new file mode 100644 index 0000000..170cd79 --- /dev/null +++ b/src/day06.rs @@ -0,0 +1,132 @@ +use std::io::Read; +use std::error::Error; +use std::fs::File; + +pub fn run(input_file: &str) -> Result<(), Box> { + let mut f = File::open(input_file)?; + let mut input = String::new(); + f.read_to_string(&mut input)?; + + let res = run_part1(&input)?; + println!("{res}"); + + let res = run_part2(&input)?; + println!("{res}"); + + Ok(()) +} + +fn remove_trailing_char(s: &str, c: char) -> &str { + if s.ends_with(c) { + &s[..s.len() - 1] + } else { + s + } +} + +// résolution d'un polynome de degré 2 +// a*x^2 + b*x + c = 0 +// +// dans le cas particulier de cet exo, on considère qu'il y a toujours +// au moins 1 solution +// +// dans cet exo on doit gerer le cas particulier où les racines sont entières +// les racines entières sont à exclure (inégalité strict) +fn solve(a: i32, b: i32, c: i32) -> (i32, i32) { + let D: f64 = (b.pow(2) - 4 * a * c) as f64; + if D < 0.0 { + // pas de solution + unreachable!(); + } + let a: f64 = a.into(); + let b: f64 = b.into(); + let mut x1: f64 = ( -b - D.sqrt() ) / ( 2.0 * a ); + let mut x2: f64 = ( -b + D.sqrt() ) / ( 2.0 * a ); + + // gérer le cas d'egalite avec les bornes + if x1 == x1.ceil() { x1 = x1 + 1.0 } + if x2 == x2.floor() { x2 = x2 - 1.0 } + + (x1.ceil() as i32, x2.floor() as i32) +} + +fn run_part1(input: &str) -> Result> { + println!("Running day06 - part 1"); + + // pour chaque (temps t, distance d) on cherche à trouver tous les entiers x + // qui satisfont l'équation : + // + // x * ( t - x ) > d + // + // cela revient donc à résoudre l'équation x^2 - t*x + d < 0 + // et donc à chercher les racines de ce polynôme + + let input = remove_trailing_char(input, '\n'); + let (str_time, str_dst) = input.split_once('\n').unwrap(); + + let time: Vec = str_time.split_once(": ").unwrap().1.split(' ') + .filter(|v| !v.is_empty()) + .map(|v| v.parse().unwrap()) + .collect(); + let dst: Vec = str_dst.split_once(": ").unwrap().1.split(' ') + .filter(|v| !v.is_empty()) + .map(|v| v.parse().unwrap()) + .collect(); + + let solutions: Vec<(i32, i32)> = time.iter().zip(dst.into_iter()) + .map(|(t, d)| { + solve(1, -t, d) + }) + .collect(); + + let res = solutions.iter() + .filter(|(x1, x2)| x1 <= x2) + .map(|(x1, x2)| x2 - x1 + 1) + .product(); + Ok(res) +} + +fn run_part2(input: &str) -> Result> { + println!("Running day06 - part 2"); + let res = 0; + Ok(res) +} + +#[cfg(test)] +mod tests { + use super::*; + + static TEXT_INPUT: &str = "\ +Time: 7 15 30 +Distance: 9 40 200"; + + #[test] + fn solve_1() { + // x^2 - 5*x + 4 = 0 + // D = 9 (x1,x2) = (1,4) + // ce sont des solutions exactes, donc on decale +1/-1 + let (x1, x2) = solve(1, -5, 4); + assert_eq!((x1, x2), (2, 3)); + } + + #[test] + fn solve_2() { + // 2*x^2 - 4*x + 2 = 0 + // D = 0 et (x1,x2) = (1,1) + // ce sont des solutions exactes, donc on decale +1/-1 + let (x1, x2) = solve(2, -4, 2); + assert_eq!((x1, x2), (2, 0)); + } + + #[test] + fn day06_part1() { + let res = run_part1(TEXT_INPUT); + assert_eq!(288, res.unwrap()); + } + + #[test] + fn day06_part2() { + let res = run_part2(TEXT_INPUT); + assert_eq!(0, res.unwrap()); + } +} diff --git a/src/main.rs b/src/main.rs index 9453932..ae0262c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ pub mod day02; pub mod day03; pub mod day04; pub mod day05; +pub mod day06; fn main() { let args: Vec = env::args().collect(); @@ -31,6 +32,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box> { "day03" => day03::run(input_file)?, "day04" => day04::run(input_file)?, "day05" => day05::run(input_file)?, + "day06" => day06::run(input_file)?, _ => return Err(format!("unknown day \"{day}\"").into()), } Ok(()) -- 2.39.5