2
votes

Given a set of integral coordinates, check whether all the points given lie on side of a possible square such that axis of the square so formed lie parallel to both X-axis and Y-axis. If such a square is possible give the minimum possible side of the square.

Suppose points are (0,0), (1,1), (2,2).
Answer : square is not possible .

Suppose points are (0,0), (0,2), (0,5), (0,7), `(3,0).
Answer : square is possible and minimum length of the side is 7.

I tried it and came up with many corner cases and it seemed impossible to tackle them individually. I was wondering if anyone can give a more generalized approach towards this kind of problem and how to think in the right direction. Thanks in advance. Range of coordinates: -1000 <= x ,y <= 1000

The number of points is <= 50.

New edit : One more corner case : (2,0) , (0,4) , (1,5) , (5,3) Answer : Square is possible with length 5 . Corner points of the square are (0,0) , (0,5) ,(5,5) ,(5,0)

4
Please consider the new edit with a new test case.Amit Kumar
A more interesting test case is (1, 0), (0, 1), (2, 1). Square with length 2 is possible. (and btw. my answer is the only one that successfully finds that ;)Nico Schertler
@NicoSchertler Yeah, I've been wondering how everyone's been handling a similar case ((0,0), (0,1), (1,0), (2,0))Dennis Meng
Also, @AmitKumar, I'm kinda curious what approaches you tried. We're usually pretty picky about making sure people post that, but since this question's been unusually tricky, we've been looking past it. Just wondering if anyone here happened to try the same thing you did. (and had you posted it, they might've seen the problem with it earlier)Dennis Meng
@Dennis: Yeah I'm always wondering about that as well when it comes to the [algorithm] tag. The question is actually totally off-topic on SO and generally bad by Stack Exchange standards, but I'm still inclined to leave it open because it's kind of interesting and people like interesting problemsNiklas B.

4 Answers

4
votes

If you define the square through xmin, xmax, ymin and ymax, then all points must lie on one of these coordinates. I.e. the square is valid, if for all vertices v:

v.x == xmin || v.x == xmax || v.y == ymin || v.y == ymax

Candidates for the bounds are the points' bounding rectangle's bounds. If you compute these boundaries, maintain a list of vertices for each edge.

If you can't assign every vertex to an edge, it is not possible to create the square.

Now it is very likely that the rectangle is not a square. So we need to enlarge its shortest side. If we have chosen the side, we need to choose whether to move the min or max edge. That's where the list of associated vertices comes into play. For the edge to move check whether all associated vertices are also associated with another edge. Then it is safe to move this edge. If we can move neither the min nor the max edge, it is impossible to create the square.

The resulting minimal side length is the distance of the edges.

1
votes

I'm trying to think of a way to do this in a single pass, but it's late at night here and I'm tired, so...

  • Run through all the elements once and record the minimum and maximum x and y values of the whole set. The side length of the square (if it exists) will be max(xmax-xmin, ymax-ymin).

  • Run through the points again. To describe a square parallel to the axes, each point must have

    x == xmin || x == xmax || y == ymin || y == ymax,

    that is, at least one coordinate must be on the side of the square. If any point fails, then you don't have a square.

I'm pretty sure this is sufficient, but doing it in two steps seems less than optimal. This is an interesting problem though, good luck.

1
votes

The requirement of the axis helps us make following observations

  1. Every such square is bounded by two parallel vertical lines and every point on that vertical line has same X-coordinate. Let's call those coordinates maxX and minX. (One of them is smaller than other)
  2. Every such square is bounded by two parallel horizontal lines and every point on that vertical line has same Y-coordinate. Let's call those coordinates maxY and minY.
  3. This is crucial: Every point in input list must have a X-coordinate matching maxX or minX OR a Y-coordinate matching maxY or minY. (Notice the OR. If there is a point that matches neither, like (1, 1) in your earlier example, you have a counterexample).

Here is a c++-like pseudocode to compute these quantities. Assume you have an appropriate Point structure.

bool isSquare(vector<Point> points) { 
   double maxX = points[0].X;
   double minX = points[0].X;
   double maxY = points[0].Y;
   double minY = points[0].Y;

   // set maxX, minX, maxY, minY
   for(int i = 0; i < points.size(); i++) {
      maxX = max(points[i].X, maxX);
      minX = min(points[i].X, minX);
      maxY = max(points[i].Y, maxY);
      minY = min(points[i].Y, minY);
   }

   // Finally, find a point which matches neither {maxX, minX, maxY, minY}
   for(int i = 0; i < points.size(); i++) {
      if (points[i].X != maxX && points[i].X != minX && points[i].Y != maxY && points[i].Y != minY) return false;
    }

    // We are not done yet!
 }

Now passing the check in this code makes sure that the points at least form a rectangle and there is no point inside the rectangle. Making sure that the rectangle is a square is the harder part. For that part, you must check that:

  1. A point is on the corner of the rectangle., i.e., both its X-coordinate matches {maxX, minX} AND its Y-coordinate matches {maxY, minY}. If found, you then need to find the largest distance of such point from any other point on the corresponding edges.
  2. If no such corner exists, you are much better off!. In that case, length of the square-side is simply max(maxX-minX, maxY-minY).

You need to be careful while writing pseudocode for this corner-finding part and consider all cases. But I think once done, this would ultimately give the answer.

0
votes

You can tackle this with the common concept of Axis Aligned Bounding Box (ABB). Given a set of points, compute ABB: Loop once through all points and find minimum x, minimum y, maximum x and maximum y. Then the box defined by two corners, lower left corner (min_x,min_y) and upper right corner (max, max y) will need to be checked against all the points to see if they lie on its perimeter. Since coordinates are integral (no floating point errors) its fairly easy to do: for each point, either the x-coordinate or the y-coordinate must match with the corresponding coordinates of the AAB, and the other coordinate has to be within range of the other coordinates. Hope that makes sense.