1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
use regex::Regex;
use std::{fs::read_to_string, ops::Range};
#[derive(Debug, Clone, Copy)]
struct Coord(isize, isize);
#[derive(Debug, Clone)]
struct TargetArea(pub Range<isize>, pub Range<isize>);
impl TargetArea {
fn contains(&self, c: Coord) -> bool {
self.0.contains(&c.0) && self.1.contains(&c.1)
}
}
fn parse_target_area(line: &str) -> TargetArea {
let x_caps = Regex::new(r"x=([-\d]*)..([-\d]*)")
.unwrap()
.captures(line)
.unwrap();
let y_caps = Regex::new(r"y=([-\d]*)..([-\d]*)")
.unwrap()
.captures(line)
.unwrap();
TargetArea(
x_caps[1].parse().unwrap()..x_caps[2].parse::<isize>().unwrap() + 1isize,
y_caps[1].parse().unwrap()..y_caps[2].parse::<isize>().unwrap() + 1isize,
)
}
fn does_intersect(mut vx: isize, mut vy: isize, area: &TargetArea) -> bool {
let mut x = 0;
let mut y = 0;
for _ in 0.. {
x += vx;
y += vy;
vx = if vx > 0 {
vx - 1
} else if vx < 0 {
vx + 1
} else {
0
};
vy -= 1;
if area.contains(Coord(x, y)) {
return true;
} else if x > area.0.end || y < area.1.start {
return false;
}
}
unreachable!()
}
fn max_y(mut vy: isize) -> isize {
let mut y = 0;
for _ in 0.. {
y += vy;
vy -= 1;
if vy <= 0 {
return y;
}
}
unreachable!()
}
fn main() {
let area = parse_target_area(&read_to_string("./input").unwrap());
let mut max_y_found = 0;
let mut max_y_vel = Coord(0, 0);
let mut num_valid = 0;
for vx in 0..=area.0.end * 2 {
for vy in -area.1.start.abs() * 2..=area.1.start.abs() * 2 {
if does_intersect(vx, vy, &area) {
if max_y(vy) > max_y_found {
max_y_found = max_y(vy);
max_y_vel = Coord(vx, vy);
}
num_valid += 1;
}
}
}
println!("part 1: {} with velocity {:?}", max_y_found, max_y_vel);
println!("part 2: {} possible velocities", num_valid);
}
|