-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
Copy pathpolygon_points.rs
84 lines (72 loc) · 1.77 KB
/
polygon_points.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
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
type Ll = i64;
type Pll = (Ll, Ll);
fn cross(x1: Ll, y1: Ll, x2: Ll, y2: Ll) -> Ll {
x1 * y2 - x2 * y1
}
pub fn polygon_area(pts: &[Pll]) -> Ll {
let mut ats = 0;
for i in 2..pts.len() {
ats += cross(
pts[i].0 - pts[0].0,
pts[i].1 - pts[0].1,
pts[i - 1].0 - pts[0].0,
pts[i - 1].1 - pts[0].1,
);
}
Ll::abs(ats / 2)
}
fn gcd(mut a: Ll, mut b: Ll) -> Ll {
while b != 0 {
let temp = b;
b = a % b;
a = temp;
}
a
}
fn boundary(pts: &[Pll]) -> Ll {
let mut ats = pts.len() as Ll;
for i in 0..pts.len() {
let deltax = pts[i].0 - pts[(i + 1) % pts.len()].0;
let deltay = pts[i].1 - pts[(i + 1) % pts.len()].1;
ats += Ll::abs(gcd(deltax, deltay)) - 1;
}
ats
}
pub fn lattice_points(pts: &[Pll]) -> Ll {
let bounds = boundary(pts);
let area = polygon_area(pts);
area + 1 - bounds / 2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_cross() {
assert_eq!(cross(1, 2, 3, 4), 4 - 3 * 2);
}
#[test]
fn test_polygon_3_coordinates() {
let pts = vec![(0, 0), (0, 3), (4, 0)];
assert_eq!(polygon_area(&pts), 6);
}
#[test]
fn test_polygon_4_coordinates() {
let pts = vec![(0, 0), (0, 2), (2, 2), (2, 0)];
assert_eq!(polygon_area(&pts), 4);
}
#[test]
fn test_gcd_multiple_of_common_factor() {
assert_eq!(gcd(14, 28), 14);
}
#[test]
fn test_boundary() {
let pts = vec![(0, 0), (0, 3), (0, 4), (2, 2)];
assert_eq!(boundary(&pts), 8);
}
#[test]
fn test_lattice_points() {
let pts = vec![(1, 1), (5, 1), (5, 4)];
let result = lattice_points(&pts);
assert_eq!(result, 3);
}
}