Skip to content

Commit f37621b

Browse files
committed
Do rotations on candidates rather than allocate a new list
1 parent a105da7 commit f37621b

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

contents/graham_scan/code/nim/graham.nim

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from algorithm import sorted
22
from math import arctan2
3-
from sequtils import deduplicate, map
3+
from sequtils import deduplicate, map, toSeq
44
import sugar
55

66
type Point[T: SomeNumber] = tuple[x, y: T]
@@ -20,22 +20,30 @@ proc flipped_point_cmp(pa, pb: Point): int =
2020
else: 1
2121

2222
proc graham_scan(gift: seq[Point]): seq[Point] =
23-
# TODO make sure input has length >= 3
23+
assert(gift.len >= 3)
2424
let
2525
gift_without_duplicates = sorted(deduplicate(gift), flipped_point_cmp)
26-
start = gift_without_duplicates[0]
27-
candidates = sorted(gift_without_duplicates[1..^1],
28-
proc (pa, pb: Point): int =
29-
if polar_angle(start, pa) < polar_angle(start, pb): -1
30-
else: 1)
31-
# TODO take the approach outlined in the text where we perform rotations on
32-
# the candidates, rather than add to a new sequence
33-
var hull = @[start, candidates[0], candidates[1]]
34-
for candidate in candidates:
35-
while not is_counter_clockwise(hull[^2], hull[^1], candidate):
36-
discard pop(hull)
37-
add(hull, candidate)
38-
hull
26+
pivot = gift_without_duplicates[0]
27+
var
28+
points = sorted(gift_without_duplicates[1..^1],
29+
proc (pa, pb: Point): int =
30+
if polar_angle(pivot, pa) < polar_angle(pivot, pb): -1
31+
else: 1)
32+
points.insert(pivot, 0)
33+
var
34+
m = 1
35+
en = toSeq(low(points) + 2..high(points))
36+
for i in mitems(en):
37+
while is_counter_clockwise(points[m - 1], points[m], points[i]):
38+
if m > 1:
39+
m -= 1
40+
elif i == points.len:
41+
break
42+
else:
43+
i += 1
44+
m += 1
45+
swap(points[i], points[m])
46+
points[0..m]
3947

4048
when isMainModule:
4149
let

0 commit comments

Comments
 (0)