Day 17 part 1 done

This commit is contained in:
Daniel Flanagan 2021-12-17 11:36:38 -06:00
parent 0cb9b6b0cd
commit 175f0ca59b
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
3 changed files with 98 additions and 1 deletions

View file

@ -76,7 +76,7 @@ And similarly for Rust:
- [x] Day 13: [Nim](./nim/day13.nim) - [x] Day 13: [Nim](./nim/day13.nim)
- [x] Day 14: [Nim](./nim/day14.nim) - [x] Day 14: [Nim](./nim/day14.nim)
- [x] Day 15: [Nim](./nim/day15.nim) - [x] Day 15: [Nim](./nim/day15.nim)
- [ ] Day 16 - [x] Day 16: [Rust](./rust/day16.rs)
- [ ] Day 17 - [ ] Day 17
- [ ] Day 18 - [ ] Day 18
- [ ] Day 19 - [ ] Day 19

View file

@ -8,4 +8,8 @@ include = ["common.rs"]
name = "day16" name = "day16"
path = "day16.rs" path = "day16.rs"
[[bin]]
name = "day17"
path = "day17.rs"
[dependencies] [dependencies]

93
2021/rust/day17.rs Normal file
View file

@ -0,0 +1,93 @@
#![warn(clippy::all, clippy::pedantic)]
mod common;
use common::day_input;
#[derive(Debug)]
struct Vec2 { x: i64, y: i64 }
#[derive(Debug)]
struct Rect { top_left: Vec2, bottom_right: Vec2 }
fn parse_target_rect(s: &str) -> Rect {
let mut nums: Vec<Vec<i64>> =
s
.split(": ")
.nth(1).unwrap()
.split(", ")
.take(2)
.map(|s| s.split("=")
.nth(1).unwrap()
.split("..")
.map(|s2| {
println!("Parsing Int: {}", s2);
s2.parse::<i64>().unwrap()
})
.take(2)
.collect()
).collect();
let mut xr: Vec<i64> = nums.remove(0);
let mut yr: Vec<i64> = nums.remove(0);
xr.sort();
yr.sort();
Rect { top_left: Vec2 { x: xr[0], y: yr[1] }, bottom_right: Vec2 { x: xr[1], y: yr[0] } }
}
fn simulate_shot(initial_vel: Vec2, target: &Rect) -> Result<(Vec2, i64), (Vec2, Vec2)> {
let mut vel = Vec2 { x: initial_vel.x, y: initial_vel.y };
let mut last_pos = Vec2 { x: 0, y: 0 };
let mut x: i64 = 0;
let mut y: i64 = 0;
let mut highest_y = y;
while x <= target.bottom_right.x && y >= target.bottom_right.y {
// println!("At {}, {} (lim: {}->{}, {}->{})", x, y, target.top_left.x, target.bottom_right.x, target.top_left.y, target.bottom_right.y);
if x >= target.top_left.x && y <= target.top_left.y && x <= target.bottom_right.x && y >= target.bottom_right.y {
// println!("Ding!: {}, {} (lim: {}->{}, {}->{})", x, y, target.top_left.x, target.bottom_right.x, target.top_left.y, target.bottom_right.y);
return Ok((Vec2 { x, y }, highest_y));
}
last_pos = Vec2 { x, y };
x += vel.x;
y += vel.y;
if vel.x != 0 {
if vel.x > 0 { vel.x -= 1; }
else { vel.x += 1; }
}
if y > highest_y { highest_y = y; }
vel.y -= 1
}
// println!("Too Far: {}, {} (lim: {}->{}, {}->{})", x, y, target.top_left.x, target.bottom_right.x, target.top_left.y, target.bottom_right.y);
Err((Vec2 { x, y }, last_pos))
}
fn trick_shot(r: &Rect) -> Option<i64> {
let mut result = None;
for x in 1..=r.top_left.x {
for y in r.bottom_right.y..=2000 {
println!("Simulating {}, {}", x, y);
if let Ok((v, hy)) = simulate_shot(Vec2 { x, y }, r) {
if result.is_some() {
if hy > result.unwrap() { result = Some(hy); }
} else {
println!("!! New Highest Y: {} via {}, {}", hy, x, y);
result = Some(hy);
}
}
}
}
result
}
fn main() {
let r = parse_target_rect(&day_input(17).trim());
println!("Trick Shot Apex: {}", trick_shot(&r).unwrap());
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn packet_op_result_examples() {
let tester = |s: &str| trick_shot(&parse_target_rect(s));
assert_eq!(tester("target area: x=20..30, y=-10..-5").unwrap(), 45);
}
}