Programming Challenge: Polygon analysis.
It's time for another programming challenge!
Given a list of coordinate pairs on a 2D plane that describe the vertices of a polygon, determine whether the polygon is concave or convex.
Since a polygon could potentially be any shape if we don't specify which vertices connect to which, we'll assume that the coordinates are given in strict order such that adjacent coordinates in the list are connected. Specifically, if we call the list V[1, n]
and say that V[i] <-> V[j]
means "vertex i and vertex j are connected", then for each arbitrary V[i]
we have V[i-1] <-> V[i] <-> V[i+1]
. Moreover, since V[1]
and V[n]
are at the ends of the list, V[1] <-> V[n]
holds (i.e. the list "wraps around").
Finally, for simplicity we can assume that all coordinates are unique, that all polygon descriptions generate valid polygons with 3 or more non-overlapping sides, and that, yes, we're working with coordinates that exist in the set of real numbers only. Don't over-complicate it :)
For those who want an even greater challenge, extend this out to work with 3D space!
Run it:
Just FYI, you can use syntax-highlighting for programming languages on Tildes if you specify the language of the code after the initial triple-backtick:
https://docs.tildes.net/text-formatting#preformatted-text-and-code
Thanks! I didn’t use a triple-backtick originally, I just used a code block by indenting lines.
This is great! Very pythonic answer.
I originally tried to go through and check if there were any interior angles greater than 180 degrees. Unfortunately, math is definitely not my strong suit and I wasn't able to figure out how to calculate the correct angle from vectors.
There's good news though, I was able to figure out a much shorter approach that checks directionality instead. I think it's close to what @onyxleopard did from this link regarding cross products.
Here's my solution, in Ruby.
output:
While you say that math is not your strong suit, you have unconsciously done exactly what is required to check if the angle is greater than 180 degrees. If a and b are vectors which lie on the xy plane, then their cross product is equal to this:
figure
equation
The sign of the right side depends only on the sign of sin, and:
equation
(this is a simplification, but you get the idea). And since phi is counted counter-clockwise from a to b, either every cross you calculate must be positive (when the vertices are oriented counter-clockwise) , or negative (when the vertices are clockwise).
I also started down the angles route (and I even left in some of the fruits of my labor down that line in my solution in the
Polygon.angles
method). And I gave up on it when I couldn’t figure out how to orient the angles. That’s when I remembered the ‘direction’ trick.Yeah, that's exactly where I gave up on that approach too. Thanks for blazing the trail :)
I wanted to make sure I actually knew what was happening in my earlier Ruby solution and that I didn't just luck into some Ruby magic, so I reimplemented that same solution in Java.
output:
That’s too easy. Given a set of points on a plane, there is no more than one convex polygon with all vertices in those points.
If you have an ordered list, you can just start with the first vertex and check if the next angle is always less than 180 degrees (considering two cases, since the list can be oriented either clockwise or counter-clockwise).
If it’s so easy, why don’t you write a program to do it ;)
The point of the challenges is to practice programming, not solve a hard problem.
Additionally, the fun of a programming challenge is figuring out how to solve it in the first place. There are quite a few programmers who are either math-averse or don't have a mathematics background in general, so the "angle greater than 180 degrees" solution may not be obvious to many. There are also other ways to solve the problem without that concept in mind (e.g. determining via a count of shifts in directionality), so part of the fun is also seeing how other people approach the problem. You could also discuss submitted solutions to determine the pros and cons of using one over the other in terms of anything from efficiency to generic extensions to long-term maintainability.
Yes, that’s a good point. I am fairly math averse myself (and the math I have studied a bit is discrete math). I just so happened to have remembered hearing of using the z component of the cross product of vectors to compute the 'direction' (there’s probably a term of art for this?) of 2d vectors here. So I sort of cheated here because I didn’t know the math, I just implemented it.
By too easy, I mean that the assumption that the points are given in a strict order is unnecessary, and makes the problem trivial. There’s little fun in solving trivial puzzles. Just modify the assumptions, and it gets a little more interesting (though still not very hard):
Given a list of coordinate pairs on a 2D plane, determine whether you can draw a convex polygon with vertices in each of the points.
Not all problems are intended to be difficult. I like to give a mix of easy, intermediate, and difficult problems so that less experienced programmers aren't alienated. Everyone should be able to participate.
Non-mathematics person chiming in here. I have no idea what I'm doing with vectors, so this problem is on the harder side of the challenges that you've posted that I've completed. Seeing someone say "this is so easy it's trivial" is more than a little discouraging.
Don’t get discouraged by mathy people saying something is trivial. There’s an old joke that I heard from one of my undergrad professors that ‘trivial’ in math is code for ‘I’m too lazy to work this out fully’.
This is why I was certain to mention that there are programmers like yourself who may not have a mathematics background (or don't have a background in that particular area of mathematics). Certain problems are going to feel trivial to certain people because those people have a particular background in some field, and for others the problems can be fairly difficult because of that lack of background. This is a reality that professional programmers experience every day.
It's for this reason that I haven't adopted a "difficulty" scale of any kind for these programming challenges. It would be so arbitrary as to be completely useless, and unlucky beginner programmers in particular who see "easy" and just happen to not do well with the particular problem may end up throwing in the proverbial towel altogether.
Please try not to feel discouraged. I've seen some of your past contributions and you're doing perfectly fine.
Thank you, I appreciate it! Thank you for posting these as well.
No problem!
Also, for the record, I just spent the last hour taking a crack at this problem and ended up rage-quitting because I found that my solution required a lot of reworking to get things to function correctly. You have me beat by default. So there's that ;)