Although the rules of chess don't allow Kings to threaten each other, this is a good geometric analogy for the real problem.
Given the following geometry
K1 [] [] [] []
K2 K3 [] [] []
[] K4 [] K5 []
the result of the required algorithm should be a data structure with the following entries: [K1, K2], [K1, K3], [K2, K3], [K2, K4], [K3, K4]
.
- The order inside an entry does not matter, so
[Kx, Ky]
is the same as[Ky, Kx]
. - The entries in the data structure don't need to be ordered.
- Kings have 0 to 8 other Kings adjacent.
The following code exists:
class King {
Point location; // Point contains x and y fields corresponding to the grid
Point getLocation() { return location; }
}
class Square {
Point location;
Point getLocation() { return location; }
King king; // null if there is no King in the square
King getKing() { return king; }
}
and also the utility method
static List<Square> getThreatenedSquares(Point location) { ... }
which returns the 8 Square
s adjacent to the given coordinates. None of the above has to be used, it's just available.
The input is Collection<King> kingsColl
, containing all Kings on the board in no relevant order (it's LinkedHashMap#values()
). My current non-stream algorithm, in words, iterates over all Kings, for each one it looks at all Kings which weren't already looked at, and checks for a matching condition.
List<King> kings = new ArrayList<>(kingsColl);
if (kings.size() > 1) {
Map<King, King> conflicts = new HashMap<>();
for (int i = 0; i < kings.size() - 1; i++) { // if the last king has a conflict, it would show up in the other king
King k1 = kings.get(i);
Point loc1 = k1.getLocation();
List<Square> adj = getThreatenedSquares(loc1);
for (int j = i + 1; j < kings.size(); j++) { // avoids duplicates Kx <-> ky
King k2 = kings.get(j);
Point loc2 = k2.getLocation();
for (Square sqr : adj) { // check for adjacency
if (sqr.getLocation().equals(loc2)) {
conflicts.put(k1, k2);
}
}
}
}
}
This algorithm is bad because it relies on indexes and requires the creation of an index-access collection, it can't be parallelized, and it makes more checks than it needs. Note that the result here is stored in a Map
, but any collection of pairs is fine (Guava included).
Iv'e tried a few ideas using streams, none of which I cared to post because they were a mess (if someone isn't convinced I will post the common "what have you tried?"). Streams tend to solve the above problem because they are implementation independent. How do I achieve this algorithm using streams?