-
-
Notifications
You must be signed in to change notification settings - Fork 18
/
main.rs
54 lines (51 loc) · 1.48 KB
/
main.rs
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
pub fn main() {
let (x, y) = include_str!("../input.txt")
.trim()
.trim_start_matches("target area: x=")
.split_once(", y=")
.unwrap();
let (x, y) = (x.split_once("..").unwrap(), y.split_once("..").unwrap());
let target: (_, i32, _, _) = (
x.0.parse().unwrap(),
y.0.parse().unwrap(),
x.1.parse().unwrap(),
y.1.parse().unwrap(),
);
println!(
"{}",
(1..=target.2)
.flat_map(|vx| {
let range = target.1.abs();
(-range..=range).filter(move |&vy| fire(target, (vx, vy)))
})
.count()
);
}
fn fire(target: (i32, i32, i32, i32), mut v: (i32, i32)) -> bool {
let mut p = (0, 0);
if v.1 > 1 {
for _ in 0..v.1 * 2 + 1 {
p.0 += v.0;
v.0 -= 1;
if p.0 > target.2 {
return false;
} else if v.0 == 0 {
break;
}
}
v.1 = -v.1 - 1;
}
for (x, y, vx, _) in path(p, v) {
if vx == 0 && x < target.0 || x > target.2 || y < target.1 {
return false;
} else if x >= target.0 && x <= target.2 && y >= target.1 && y <= target.3 {
return true;
}
}
unreachable!();
}
fn path(p: (i32, i32), v: (i32, i32)) -> impl Iterator<Item = (i32, i32, i32, i32)> {
std::iter::successors(Some((p.0, p.1, v.0, v.1)), |p| {
Some((p.0 + p.2, p.1 + p.3, (p.2 - 1).max(0), p.3 - 1))
})
}