]> aoc.elinar.fr Git - aoc_2023/commitdiff
Day06 - part 1
authoralex <null>
Wed, 6 Dec 2023 10:17:00 +0000 (11:17 +0100)
committeralex <null>
Wed, 6 Dec 2023 10:17:30 +0000 (11:17 +0100)
src/day06.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day06.rs b/src/day06.rs
new file mode 100644 (file)
index 0000000..170cd79
--- /dev/null
@@ -0,0 +1,132 @@
+use std::io::Read;
+use std::error::Error;
+use std::fs::File;
+
+pub fn run(input_file: &str) -> Result<(), Box<dyn Error>> {
+    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<i32, Box<dyn Error>> {
+    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<i32> = str_time.split_once(": ").unwrap().1.split(' ')
+        .filter(|v| !v.is_empty())
+        .map(|v| v.parse().unwrap())
+        .collect();
+    let dst: Vec<i32> = 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<i32, Box<dyn Error>> {
+    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());
+    }
+}
index 94539329855e5410bb27f8860276486171e21c21..ae0262cfccf712596712c2119db6f81675aada12 100644 (file)
@@ -8,6 +8,7 @@ pub mod day02;
 pub mod day03;
 pub mod day04;
 pub mod day05;
+pub mod day06;
 
 fn main() {
     let args: Vec<String> = env::args().collect();
@@ -31,6 +32,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box<dyn Error>> {
         "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(())