Skip to content

Commit 28896b9

Browse files
authored
Added Graham scan in Coconut (#725)
1 parent 3005e35 commit 28896b9

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from math import atan2
2+
3+
4+
data point(x=0, y=0):
5+
def angle(self, other):
6+
"""Computes the angle between the two points"""
7+
match point(x1, y1) in other:
8+
return atan2(y1 - self.y, x1 - self.x)
9+
def __str__(self):
10+
return f'({self.x}, {self.y})'
11+
12+
# Is the turn counter-clockwise?
13+
def counter_clockwise(p1, p2, p3) =
14+
(p3.y - p1.y) * (p2.x - p1.x) >= (p2.y - p1.y) * (p3.x - p1.x)
15+
16+
17+
def graham_scan(gift):
18+
gift = list(set(gift)) # Remove the duplicate points if any.
19+
start = min(gift, key=(p -> (p.x, p.y)))
20+
gift.remove(start)
21+
22+
s = sorted(gift, key=(point -> start.angle(point)))
23+
hull = [start, s[0], s[1]]
24+
25+
# Remove the hull points that make the hull concave
26+
for point in s[2:]:
27+
while not counter_clockwise(hull[-2], hull[-1], point):
28+
del hull[-1]
29+
hull.append(point)
30+
return hull
31+
32+
33+
if __name__ == '__main__':
34+
test_gift = [
35+
(-5, 2),
36+
(5, 7),
37+
(-6, -12),
38+
(-14, -14),
39+
(9, 9),
40+
(-1, -1),
41+
(-10, 11),
42+
(-6, 15),
43+
(-6, -8),
44+
(15, -9),
45+
(7, -7),
46+
(-2, -9),
47+
(6, -5),
48+
(0, 14),
49+
(2, 8),
50+
] |> map$(p -> point(*p)) |> list
51+
hull = graham_scan(test_gift)
52+
"The points in the hull are:" |> print
53+
"\n".join(map(str, hull)) |> print

contents/graham_scan/graham_scan.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ We can find whether a rotation is counter-clockwise with trigonometric functions
3030
[import:5-13, lang:"lisp"](code/clisp/graham-scan.lisp)
3131
{% sample lang="cpp" %}
3232
[import:18-20, lang="cpp"](code/c++/graham_scan.cpp)
33+
{% sample lang="coco" %}
34+
[import:4-8, lang="coconut"](code/coconut/graham_scan.coco)
3335
{% endmethod %}
3436

3537
If the output of this function is 0, the points are collinear.
@@ -62,6 +64,8 @@ In the end, the code should look something like this:
6264
[import:15-58, lang:"lisp"](code/clisp/graham-scan.lisp)
6365
{% sample lang="cpp" %}
6466
[import:26-62, lang="cpp"](code/c++/graham_scan.cpp)
67+
{% sample lang="coco" %}
68+
[import:17-30, lang="coconut"](code/coconut/graham_scan.coco)
6569
{% endmethod %}
6670

6771
### Bibliography
@@ -89,6 +93,8 @@ In the end, the code should look something like this:
8993
[import, lang:"lisp"](code/clisp/graham-scan.lisp)
9094
{% sample lang="cpp" %}
9195
[import, lang="cpp"](code/c++/graham_scan.cpp)
96+
{%sample lang="coco" %}
97+
[import, lang="coconut"](code/coconut/graham_scan.coco)
9298
{% endmethod %}
9399

94100
<script>

0 commit comments

Comments
 (0)