Skip to content

Commit b4ee101

Browse files
committed
Add ARMBH, convexHull
1 parent aac6c1d commit b4ee101

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed

codechef/haskell/ARMBH1.hs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
cases = "1 \
2+
\3 10 \
3+
\3 15"
4+
5+
find :: [Integer] -> [Integer]
6+
find (x:y:rest) = sum [x, x * 2 .. (y-1)] : find rest
7+
find _ = []
8+
9+
solve = mapM_ print . find . map read . tail . words
10+
11+
main = getContents >>= solve

hackerrank/haskell/convexHullFP.hs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
-- import Data.List
2+
-- import Data.Tuple
3+
4+
-- type Point = (Double, Double)
5+
6+
-- hull :: [Point] -> [Point]
7+
-- hull l = filterPoints (orderByPolarAngel (findStart l) l)
8+
9+
-- filterPoints :: [Point] -> [Point]
10+
-- filterPoints (x:y:z:xs)
11+
-- | ccw x y z = x : filterPoints (y : z : xs)
12+
-- | otherwise = x : filterPoints (z : xs)
13+
-- filterPoints x = x
14+
15+
-- ccw :: Point -> Point -> Point -> Bool
16+
-- ccw (x1, y1) (x2, y2) (x3, y3) = (x2 - x1)*(y3 - y1) - (y2 - y1)*(x3 - x1) >= 0
17+
18+
-- orderByPolarAngel :: Point -> [Point] -> [Point]
19+
-- orderByPolarAngel p = sortBy (polarAngelCompare p)
20+
-- where polarAngelCompare = \ f p1 p2 -> compare (polarAngel f p2) (polarAngel f p1)
21+
-- polarAngel = \ (x1, y1) (x2, y2) -> (x2-x1)/(y2-y1)
22+
23+
-- findStart :: [Point] -> Point
24+
-- findStart = swap . minimum . map swap
25+
26+
27+
import Text.Printf
28+
import Data.List
29+
30+
type Point = (Double, Double)
31+
32+
-- Euclidean distance
33+
dist :: (Double, Double) -> (Double, Double) -> Double
34+
dist (x1, y1) (x2, y2) = sqrt (f x1 x2 + f y1 y2)
35+
where f a b = (a - b)^2
36+
37+
-- Use Graham scan, https://en.wikipedia.org/wiki/Graham_scan
38+
-- Three points are a counter-clockwise turn if ccw > 0, clockwise if
39+
-- ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
40+
-- gives twice the signed area of the triangle formed by p1, p2 and p3.
41+
ccv :: Num a => (a, a) -> (a, a) -> (a, a) -> a
42+
ccv (x1, y1) (x2, y2) (x3, y3) = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)
43+
44+
-- Find bottom-most point taking into account the x coordinate
45+
findMinYPoint :: [Point] -> Point
46+
findMinYPoint (p:points) = f p points
47+
where
48+
f prev [] = prev
49+
f p0@(x0,y0) (p1@(x1,y1):points) | y1 < y0 = f p1 points
50+
-- NB: select point with smaller x if y's are equal
51+
| (y1 == y0) && (x1 < x0) = f p1 points
52+
| otherwise = f p0 points
53+
54+
filterSameAngle :: [(Point, Double)] -> [Point]
55+
filterSameAngle lst = map fst . filter snd $ r
56+
where
57+
r = zipWith (\(pa, ra) (pb, rb) -> (pa, ra /= rb)) lst (drop 1 lst ++ [head lst])
58+
59+
pretty :: [Point] -> String
60+
pretty = unlines . map h
61+
where h (x, y) = printf "\t%0.f %.0f" x y
62+
63+
build :: [Point] -> [Point] -> [Point]
64+
build hull [] = hull
65+
build hs@[h1] ps@(p:points) = build ([p, h1]) points
66+
build hs@(h2:h1:hull) ps@(p:points) = hull'
67+
where
68+
rightTurn = ccv h1 h2 p < 0
69+
collinear = ccv h2 h1 p == 0
70+
hull' | rightTurn = build (h1:hull) ps -- Remove head and retry
71+
| collinear = build (p:h1:hull) points -- Replace the head with p
72+
| otherwise = build (p:hs) points -- Add p
73+
74+
convexHull :: [(Double, Double)] -> [(Double, Double)]
75+
convexHull points = hull
76+
where
77+
-- 1) Find the bottom-most point
78+
p0@(x0, y0) = findMinYPoint points
79+
80+
-- 2) Sort in increasing order of the angle they and the point P make with the x-axis
81+
sorted' = let
82+
o (a, ra) (b, rb) | ra > rb = GT
83+
-- NB: Nearest points first, further points GT
84+
| (ra == rb) && (dist a p0 > dist b p0) = GT
85+
| otherwise = LT
86+
in sortBy o hullP
87+
88+
-- For performance, instead of atan, do not calculate the
89+
-- angle. Use e.g. cos for ordering intead
90+
f (x, y) = r'
91+
where r = atan $ (y - y0) / (x - x0)
92+
-- NB: Avoid negative angles values
93+
r' | r < 0 = r + 2*pi
94+
| otherwise = r
95+
96+
hullP = map (\p -> (p, f p)) $ delete p0 points
97+
98+
-- 3) NB: Remove points with same angles that are closer from p0
99+
sorted = filterSameAngle sorted'
100+
101+
-- 4) Recursively build the convex hull
102+
hull = build [p0] sorted
103+
104+
distance p1 p2 = sqrt ((x2 - x1) ** 2 + (y2 - y1) ** 2)
105+
where x1 = fst p1
106+
x2 = fst p2
107+
y1 = snd p1
108+
y2 = snd p2
109+
110+
repeatFirst x = take (length x + 1) (cycle x)
111+
112+
findDist :: [(Double, Double)] -> [Double]
113+
findDist [] = []
114+
findDist [x] = []
115+
findDist (x:xs) = distance x (head xs) : findDist xs
116+
117+
-- makes pair of the alternative elements in the list
118+
makeP :: [Double] -> [Point]
119+
makeP (x:y:rest) = (x,y) : makeP rest
120+
makeP _ = []
121+
122+
cases = "6 \
123+
\1 1 \
124+
\2 5 \
125+
\3 3 \
126+
\5 3 \
127+
\3 2 \
128+
\2 2"
129+
130+
solve :: String -> IO ()
131+
solve = printf "%.1f\n" . sum . findDist . repeatFirst . convexHull . makeP . map read . tail . words
132+
133+
main = getContents >>= solve

0 commit comments

Comments
 (0)