|
| 1 | +data point(x=0, y=0): |
| 2 | + def __str__(self): |
| 3 | + return f'({self.x}, {self.y})' |
| 4 | + |
| 5 | +# Is the turn counter-clockwise? |
| 6 | +def counter_clockwise(p1 is point, p2 is point, p3 is point) = |
| 7 | + (p3.y - p1.y) * (p2.x - p1.x) >= (p2.y - p1.y) * (p3.x - p1.x) |
| 8 | + |
| 9 | + |
| 10 | +def jarvis_march(gift: point[]) -> point[]: |
| 11 | + point_on_hull = min(gift) # The leftmost point in the gift |
| 12 | + hull = [point_on_hull] # It is guaranteed it will be on the hull. |
| 13 | + |
| 14 | + while True: |
| 15 | + # Candidate for the next point in the hull |
| 16 | + endpoint = gift[0] |
| 17 | + for p in gift: |
| 18 | + if (endpoint == point_on_hull |
| 19 | + or not counter_clockwise(p, hull[-1], endpoint)): |
| 20 | + endpoint = p |
| 21 | + |
| 22 | + point_on_hull = endpoint |
| 23 | + |
| 24 | + # Check if the gift is completely covered. |
| 25 | + if hull[0] == endpoint: |
| 26 | + return hull |
| 27 | + hull.append(point_on_hull) |
| 28 | + |
| 29 | + |
| 30 | +if __name__ == '__main__': |
| 31 | + test_gift = [ |
| 32 | + (-5, 2), (5, 7), (-6, -12), (-14, -14), (9, 9), |
| 33 | + (-1, -1), (-10, 11), (-6, 15), (-6, -8), (15, -9), |
| 34 | + (7, -7), (-2, -9), (6, -5), (0, 14), (2, 8) |
| 35 | + ] |> map$(t -> point(*t)) |> list |
| 36 | + hull = jarvis_march(test_gift) |
| 37 | + |
| 38 | + print("[#] The points in the hull are:") |
| 39 | + for point in hull: |
| 40 | + print(point) |
0 commit comments