public static int FindBestRegion(IEnumerable <string> input, int maxDistance) { var locations = input.Select((s, i) => Loc.FromString(i + 1, s)).ToList(); // borders var fromX = locations.Min(l => l.X); var toX = locations.Max(l => l.X); var fromY = locations.Min(l => l.Y); var toY = locations.Max(l => l.Y); // for each coordinate, compute the sum of the distances to all coordinates var sumDistanceMap = Enumerable.Range(fromX, toX - fromX + 1) .SelectMany(x => Enumerable.Range(fromY, toY - fromY + 1) .Select(y => new { X = x, Y = y, SumOfDistances = locations.Select(l => l.DistanceTo(x, y)).Sum() })); return(sumDistanceMap.Count(c => c.SumOfDistances < maxDistance)); }
public static int FindBestLocationArea(IEnumerable <string> input) { // idea -> iterate over the smallest grid (as defined by (min,max) coordinates) // for every point compute the closest coord and increase the counter for it // solution is max of those counters for those who are not infinite // a location has infinite area when a border point is closest to that location var locations = input.Select((s, i) => Loc.FromString(i + 1, s)).ToList(); // borders var fromX = locations.Min(l => l.X); var toX = locations.Max(l => l.X); var fromY = locations.Min(l => l.Y); var toY = locations.Max(l => l.Y); // helper function int ClosestLocationFrom(int x, int y) { var distances = locations.Select(l => new { l.Id, Distance = l.DistanceTo(x, y) }); var minDistance = distances.Min(d => d.Distance); var minDistanceLocs = distances.Where(d => d.Distance == minDistance).ToList(); return(minDistanceLocs.Count == 1 ? minDistanceLocs[0].Id : 0); // 0 means: multiple locations closer } // compute closest location for each point of the grid var closestLocations = Enumerable.Range(fromX, toX - fromX + 1) .SelectMany(x => Enumerable.Range(fromY, toY - fromY + 1) .Select(y => new { X = x, Y = y, Closest = ClosestLocationFrom(x, y) })); // find all the "infinite locations" (i.e. they touch the border) and remove them, also remove non-clear locations (0) var locationsWithInfiniteArea = closestLocations.Where(l => l.Closest == 0 || l.X == fromX || l.X == toX || l.Y == fromY || l.Y == toY).Select(l => l.Closest).ToHashSet(); var closestLocationsWithoutInfinites = closestLocations.Where(l => !locationsWithInfiniteArea.Contains(l.Closest)); // count what's left and select the winner var areas = closestLocationsWithoutInfinites.GroupBy(l => l.Closest).Select(gl => new { Id = gl.Key, Count = gl.Count() }); var maxArea = areas.Max(a => a.Count); var maxAreaId = areas.First(a => a.Count == maxArea); // for info only return(maxArea); }