From 8ab440a765cc9502d5ab103f54782d0f2e41125d Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Fri, 24 Dec 2021 23:17:06 +0100 Subject: [PATCH] Added day 17 code for part 1 and 2 Signed-off-by: Louis Vallat --- .gitlab-ci.yml | 5 ++++ day17/Cargo.toml | 8 ++++++ day17/input | 1 + day17/src/main.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 day17/Cargo.toml create mode 100644 day17/input create mode 100644 day17/src/main.rs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 72daea1..16b85d0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -83,3 +83,8 @@ day-16: stage: build script: - cd day16; cargo run --release ./input + +day-17: + stage: build + script: + - cd day17; cargo run --release ./input diff --git a/day17/Cargo.toml b/day17/Cargo.toml new file mode 100644 index 0000000..e483073 --- /dev/null +++ b/day17/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day17" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day17/input b/day17/input new file mode 100644 index 0000000..6b9ce9e --- /dev/null +++ b/day17/input @@ -0,0 +1 @@ +target area: x=25..67, y=-260..-200 diff --git a/day17/src/main.rs b/day17/src/main.rs new file mode 100644 index 0000000..cfc91bc --- /dev/null +++ b/day17/src/main.rs @@ -0,0 +1,67 @@ +use std::{fs, env}; + +fn read_input(path: &str) -> String { + return fs::read_to_string(path).expect("Cannot read file."); +} + +fn parse_input(s: &str) -> ((i32, i32), (i32, i32)) { + let v = s.trim_end_matches("\n") + .split_once("x=").unwrap() + .1.split_once(", y=").unwrap(); + let s = v.0.split_once("..").unwrap(); + let e = v.1.split_once("..").unwrap(); + return ((s.0.parse().unwrap(), s.1.parse().unwrap()), + (e.0.parse().unwrap(), e.1.parse().unwrap())); +} + +fn has_crossed(p: &(i32, i32), z: &((i32, i32), (i32, i32))) -> bool { + return p.0 > z.0.1 || p.1 < z.1.0; +} + +fn is_in(p: &(i32, i32), z: &((i32, i32), (i32, i32))) -> bool { + return p.0 >= z.0.0 && p.0 <= z.0.1 && p.1 >= z.1.0 && p.1 <= z.1.1; +} + +fn compute_trajectory(mut v: (i32, i32), z: &((i32, i32), (i32, i32)), t: &mut Vec<(i32, i32)>) { + let mut l = t.last().unwrap_or(&(0, 0)).to_owned(); + while !(has_crossed(&l, z) || is_in(&l, z)) { + l.0 += v.0; + l.1 += v.1; + v.0 += if v.0 > 0 { -1 } else if v.0 < 0 { 1 } else { 0 }; + v.1 -= 1; + t.push(l); + } +} + +fn get_max_y(v: &Vec<(i32, i32)>) -> i32 { + return v.iter().fold(i32::MIN, |acc, e| if e.1 > acc { e.1 } else { acc }); +} + +fn get_optimized_trajectory(z: &((i32, i32), (i32, i32))) -> (i32, usize) { + let mut v = vec![]; + for i in 0..700 { + for j in -300..700 { + let mut b = vec![]; + compute_trajectory((i, j), z, &mut b); + if is_in(b.last().unwrap(), z) { v.push(b); } + } + } + let mut max = i32::MIN; + for i in v.clone() { + let m = get_max_y(&i); + if m > max { max = m; } + } + return (max, v.len()); +} + +fn main() { + let args: Vec = env::args().collect(); + for arg in args.iter().skip(1) { + let input = read_input(&arg); + let vec_in = parse_input(&input); + let a = get_optimized_trajectory(&vec_in); + println!("[{}]", &arg); + println!("\t[Part 1] => Answer is '{}'.", a.0); + println!("\t[Part 2] => Answer is '{}'.", a.1); + } +}