From 8e2720c3e421674615eac29bf4c02528a53f2606 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sat, 15 Jan 2022 03:20:12 +0200 Subject: [PATCH] feat: solve day 17 part 1 & 2 --- input/17.txt | 1 + src/day17.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 3 ++ 3 files changed, 106 insertions(+) create mode 100644 input/17.txt create mode 100644 src/day17.rs diff --git a/input/17.txt b/input/17.txt new file mode 100644 index 0000000..ae66f1f --- /dev/null +++ b/input/17.txt @@ -0,0 +1 @@ +target area: x=29..73, y=-248..-194 diff --git a/src/day17.rs b/src/day17.rs new file mode 100644 index 0000000..5d5d11d --- /dev/null +++ b/src/day17.rs @@ -0,0 +1,102 @@ + +pub struct Rect { + x0: i32, x1: i32, + y0: i32, y1: i32, +} + +pub fn parse_input(input: &str) -> Rect { + let (x_part, y_part) = input.strip_suffix("\n") + .or(Some(input)) + .unwrap() + .strip_prefix("target area: ") + .unwrap() + .split_once(", ") + .unwrap(); + let (x0, x1) = x_part[2..].split_once("..").unwrap(); + let (y0, y1) = y_part[2..].split_once("..").unwrap(); + return Rect { + x0: x0.parse().unwrap(), + x1: x1.parse().unwrap(), + y0: y0.parse().unwrap(), + y1: y1.parse().unwrap() + } +} + +fn sign(x: i32) -> i32 { + if x > 0 { 1 } else if x < 0 { -1 } else { 0 } +} + +fn is_overshot(px: i32, py: i32, target: &Rect) -> bool { + px > target.x1 || py < target.y0 +} + +fn is_in_rect(px: i32, py: i32, target: &Rect) -> bool { + target.x0 <= px && px <= target.x1 && + target.y0 <= py && py <= target.y1 +} + +fn simulate(target: &Rect, initial_vx: i32, initial_vy: i32) -> i32 { + let mut px = 0; + let mut py = 0; + let mut vx = initial_vx; + let mut vy = initial_vy; + let mut maxy = 0; + + while !is_overshot(px, py, target) { + px += vx; + py += vy; + + if is_in_rect(px, py, target) { + return maxy; + } + + maxy = maxy.max(py); + + vx -= sign(vx); + vy -= 1; + } + + return -1; +} + +pub fn part1(target: &Rect) -> i32 { + let mut maxy = 0; + for vx in 0..target.x1 { + for vy in target.y0..-target.y0 { + maxy = maxy.max(simulate(target, vx, vy)); + } + } + return maxy; +} + +pub fn part2(target: &Rect) -> i32 { + let mut count = 0; + for vx in 0..=target.x1 { + for vy in target.y0..-target.y0 { + if simulate(target, vx, vy) >= 0 { + count += 1; + } + } + } + return count; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example() { + let target = parse_input("target area: x=20..30, y=-10..-5"); + let result = part1(&target); + assert_eq!(result, 45); + } + + #[test] + fn part2_example() { + let target = parse_input("target area: x=20..30, y=-10..-5"); + let result = part2(&target); + assert_eq!(result, 112); + } +} + diff --git a/src/main.rs b/src/main.rs index 21a6104..3fd5c79 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ mod day13; mod day14; mod day15; mod day16; +mod day17; use std::{env, process}; use std::fs::File; @@ -62,6 +63,8 @@ fn run(day: i32, part: i32, input_filename: &str) { "15.2" => println!("{}", day15::part2(&mut day15::parse_input(&contents))), "16.1" => println!("{}", day16::part1(&day16::parse_input(&contents))), "16.2" => println!("{}", day16::part2(&day16::parse_input(&contents))), + "17.1" => println!("{}", day17::part1(&day17::parse_input(&contents))), + "17.2" => println!("{}", day17::part2(&day17::parse_input(&contents))), _ => println!("Day {} part {} not found", day, part) } }