| public class RouterBroadcasts { |
| |
|
| |
private static class Router { |
| |
String name; |
| |
int x, y; |
| |
public Router(String name, int x, int y) { |
| |
this.name = name; |
| |
this.x = x; |
| |
this.y = y; |
| |
} |
| |
public boolean equals(Object o) { |
| |
Router router = (Router) o; |
| |
return x == router.x && y == router.y && name.equals(router.name); |
| |
} |
| |
} |
| |
|
| |
private double distance(Router a, Router b) { |
| |
return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); |
| |
} |
| |
|
| |
private boolean isInRange(Router router, Router otherRouter) { |
| |
return distance(router, otherRouter) <= 10.0; |
| |
} |
| |
|
| |
public boolean isReachable(Router start, Router target, List<Router> allRouters) { |
| |
Queue<Router> bfsQ = new LinkedList<>(); |
| |
Set<String> shutdownRouters = new HashSet<>(); |
| |
bfsQ.add(start); |
| |
while (!bfsQ.isEmpty()) { |
| |
Router broadcastRouter = bfsQ.remove(); |
| |
if (broadcastRouter.equals(target)) return true; |
| |
if (shutdownRouters.contains(broadcastRouter.name)) continue; |
| |
List<Router> routersInRange = allRouters.stream() |
| |
.filter(nextRouter -> !nextRouter.equals(broadcastRouter) |
| |
&& !shutdownRouters.contains(nextRouter.name) |
| |
&& isInRange(broadcastRouter, nextRouter)) |
| |
.collect(Collectors.toList()); |
| |
//bfsQ.addAll(routersInRange); // first version |
| |
bfsQ.addAll(nearestRouters(broadcastRouter, routersInRange)); // follow-up version |
| |
shutdownRouters.add(broadcastRouter.name); |
| |
} |
| |
return false; |
| |
} |
| |
|
| |
private List<Router> nearestRouters(Router source, List<Router> routersInRange) { |
| |
double minDistance = Double.MAX_VALUE; |
| |
HashMap<Double, List<Router>> routersByDistance = new HashMap<>(); |
| |
for (Router router : routersInRange) { |
| |
double dist = distance(source, router); |
| |
minDistance = Math.min(dist, minDistance); |
| |
routersByDistance.putIfAbsent(dist, new LinkedList<>()); |
| |
routersByDistance.computeIfPresent(dist, (d, routers) -> { |
| |
routers.add(router); |
| |
return routers; |
| |
}); |
| |
} |
| |
return routersByDistance.getOrDefault(minDistance, new LinkedList<>()); |
| |
} |
| |
|
| |
public static void main(String[] args) { |
| |
// initial version testcases |
| |
RouterBroadcasts rbc = new RouterBroadcasts(); |
| |
Router A = new Router("A", 0, 0); |
| |
Router B = new Router("B", 0, 8); |
| |
Router C = new Router("C", 0, 17); |
| |
Router D = new Router("D", 11, 0); |
| |
System.out.println(rbc.isReachable(A, B, Arrays.asList(A, B, C, D))); //true |
| |
System.out.println(rbc.isReachable(A, C, Arrays.asList(A, B, C, D))); //true |
| |
System.out.println(rbc.isReachable(A, D, Arrays.asList(A, B, C, D))); //false |
| |
// follow-up version testcases |
| |
Router E = new Router("E", 4, 0); |
| |
Router F = new Router("F", 0, 4); |
| |
Router H = new Router("H", 6, 8); |
| |
System.out.println(rbc.isReachable(A, C, Arrays.asList(A, B, C, E, F))); //true |
| |
System.out.println(rbc.isReachable(A, C, Arrays.asList(A, B, C, E, F, H))); //false |
| |
} |
| |
} |