We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Post 45
Hacker Rank 19 - Is Convex?
Published on: 2025-06-29
Tags:
elixir, Side Project, Hacker Rank
You are given the Cartesian coordinates of a set of points in a plane (in no particular order). Each of these points is a corner point of some Polygon, , which is not self-intersecting in nature. Can you determine whether or not is a concave polygon?
Sample Input
4
0 0
0 1
1 1
1 0
Sample Output
NO
Okay so for this one there was a few things that I wanted to do in order to find the right answer.
First I need to sort the points based of the centroid of the shape. To do that I needed to first find the centroid of the shape, this is a simple function that will add up all the x and y points and divide by the number of points. Once that is done we need to order the list based off the angel from the centroid of the shape.
def sort_list(points) do
number_of_points = length(points)
[cx, cy] =
Enum.reduce(points, [0, 0], fn [x, y], [cx, cy] -> [x + cx, y + cy] end)
|> (fn [x, y] -> [x / number_of_points, y / number_of_points] end).()
Enum.sort_by(points, fn [x, y] -> :math.atan2(y - cy, x - cx) end)
end
Once this is done you now have the points in the correct order going around the center of the shape.
Next step is to take the cross-product of each set of 3 points on the shape. We do this because the cross product will tell us the the direction of the points from one to the next.
def find_orientaion(points) do
full_loop = points ++ Enum.take(points, 2) # You need to add in the first 2 points to the end
Enum.chunk_every(full_loop, 3, 1, :discard)
|> Enum.map(&cross_product/1)
end
# Positive result -> A is counter-clockwise from B
# Negative result -> A is clockwise from B
defp cross_product([[x1, y1], [x2, y2], [x3, y3]]) do
(x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2)
end
This will give us a list of every cross product of each point.
Once you have this done you need to be sure that every cross-product is positive or negative. But keep in mind one thing a 0 for the cross-product means that the 3 points are in a straight line, this will mess with the logic to see if any 2 cross-products are either both positive or both negative.
(cross1 * cross2 > 0) So we need to remove the 0's from the list.
def is_convex(orientations) do
non_zero = Enum.filter(orientations, &(&1 != 0))
# If all are zero (degenerate polygon), treat as convex
if non_zero == [], do: "NO", else: convex_loop(non_zero, hd(non_zero))
end
defp convex_loop([head | tail], check) do
if head * check > 0,
do: convex_loop(tail, check),
else: "YES"
end
defp convex_loop([], _), do: "NO"
That is it... pretty simple if you know all the needed steps for the question.