diff --git a/contents/graham_scan/code/python/grahamScan.py b/contents/graham_scan/code/python/grahamScan.py new file mode 100644 index 000000000..cea09a72c --- /dev/null +++ b/contents/graham_scan/code/python/grahamScan.py @@ -0,0 +1,42 @@ +from math import atan2 + + +#Is the turn counter clockwise? +def counter_clockwise(p1, p2, p3): + return (p3[1]-p1[1])*(p2[0]-p1[0]) >= (p2[1]-p1[1])*(p3[0]-p1[0]) + + +#Find the polar angle of a point relative to a reference point +def polar_angle(ref, point): + return atan2(point[1]-ref[1],point[0]-ref[0]) + + +def graham_scan(gift): + gift = list(set(gift)) #Remove duplicate points + start = min(gift, key=lambda p: (p[1], p[0])) #Must be in hull + gift.remove(start) + + s = sorted(gift,key=lambda point: polar_angle(start, point)) + hull = [start,s[0],s[1]] + + #Remove points from hull that make the hull concave + for pt in s[2:]: + while not counter_clockwise(hull[-2], hull[-1], pt): + del hull[-1] + hull.append(pt) + + return hull + + +def main(): + test_gift = [(-5, 2), (5, 7), (-6, -12), (-14, -14), (9, 9), + (-1, -1), (-10, 11), (-6, 15), (-6, -8), (15, -9), + (7, -7), (-2, -9), (6, -5), (0, 14), (2, 8)] + hull = graham_scan(test_gift) + + print("The points in the hull are:") + for point in hull: + print(point) + + +main() diff --git a/contents/graham_scan/graham_scan.md b/contents/graham_scan/graham_scan.md index ea9f74def..9c0b941c5 100644 --- a/contents/graham_scan/graham_scan.md +++ b/contents/graham_scan/graham_scan.md @@ -20,6 +20,8 @@ We can find whether a rotation is counter-clockwise with trigonometric functions [import:24-26, lang:"c_cpp"](code/c/graham.c) {% sample lang="js" %} [import:36-38, lang:"javascript"](code/javascript/graham-scan.js) +{% sample lang="py" %} +[import:4-6, lang:"python"](code/python/grahamScan.py) {% endmethod %} If the output of this function is 0, the points are collinear. @@ -42,6 +44,8 @@ In the end, the code should look something like this: [import:65-95, lang:"c_cpp"](code/c/graham.c) {% sample lang="js" %} [import:1-30, lang:"javascript"](code/javascript/graham-scan.js) +{% sample lang="py" %} +[import:14-27, lang:"python"](code/python/grahamScan.py) {% endmethod %} ### Bibliography @@ -59,6 +63,8 @@ In the end, the code should look something like this: [import, lang:"c_cpp"](code/c/graham.c) {% sample lang="js" %} [import, lang:"javascript"](code/javascript/graham-scan.js) +{% sample lang="py" %} +[import, lang:"python"](code/python/grahamScan.py) {% endmethod %}