Closest Cells
Description
You are playing a game on a rectangular checkerboard with a specific set of rules.
Each game piece has a unique id
and each cell on the board is defined by its x
and y
coordinates.
The current positions of your pieces on the board are stored in the positions table with the following structure:
- id: unique piece id;
- x: x coordinate of the cell that the piece with id
id
occupies; - y: y coordinate of the cell that the piece with id
id
occupies.
In this game each piece on the board is said to defend its nearest neighbor. The distance between two pieces is calculated simply as the distance between the points (x1, y1)
and (x2, y2)
, where (x1, y1)
and (x2, y2)
are the coordinates of the cells occupied by the first and the second piece, respectively.
You thought it might be good idea to find what piece each of the game pieces defends.
Given the positions table, compose the resulting table with two columns: id1
and id2
, such that on each row the piece with id id1
defends the piece with id2
(i.e. id2
is the closest to id1
piece).
The table should be sorted by the values of id1
in ascending order.
It’s guaranteed that for each piece there is only one other piece closest to it.
Example
For the following tables positions
id | x | y |
---|---|---|
1 | 0 | 0 |
2 | 2 | 0 |
3 | 4 | 3 |
4 | 2 | 1 |
the output should be
id1 | id2 |
---|---|
1 | 2 |
2 | 4 |
3 | 4 |
4 | 2 |
- [execution time limit] 10 seconds (mysql)
Solution
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*Please add ; after each select statement*/
CREATE PROCEDURE closestCells()
BEGIN
SELECT DISTINCT(t.id1) as id1, t.id2 as id2
FROM ( SELECT p.id AS id1, r.id AS id2, ST_Distance(Point(p.x,p.y), Point(r.x,r.y)) AS dist
FROM positions p, positions r
WHERE p.id <> r.id
ORDER By dist) AS t INNER JOIN ( SELECT f.id1, MIN(f.dist) as dist
FROM ( SELECT p.id AS id1, r.id AS id2, ST_Distance(Point(p.x,p.y), Point(r.x,r.y)) AS dist
FROM positions p, positions r
WHERE p.id <> r.id
ORDER By dist) AS f GROUP BY f.id1) AS g ON t.id1 = g.id1 AND t.dist = g.dist
ORDER BY id1;
END