/// <summary> /// Get the shortest possible distance between any two train platforms /// </summary> /// <param name="start">Starting Point</param> /// <param name="end">Ending Point</param> /// <param name="maxDistance">Depth parameter for graph algorithm</param> /// <exception cref="RouteNotFoundException" /// <returns>distance in integrer form or a RouteNotFoundException exception</returns> public int GetShortestDistance(char start, char end, int maxDistance) { var routes = _routeRepository.GetAll(); var routeDomainItems = GetRouteDomainItemsForData(routes); RouteScenarioContainer container = new RouteScenarioContainer(start, maxDistance); TraverseRouteScenarios(routeDomainItems, ref container, true); int distance = 0; if (container.Passengers.Any()) { distance = container.Passengers .Where(m => m.RouteMap.First().CompareTo(start) == 0 && m.RouteMap.Last().CompareTo(end) == 0) .Select(m => m.DistanceTraveled) .OrderBy(m => m) .FirstOrDefault(); } if (distance == 0) { throw new RouteNotFoundException(); } return(distance); }
/// <summary> /// This is the algorithm we use the run scenarios through our rail system. We take a supplied list of routes and traverse all possible scenarios with the specific starting point. /// </summary> /// <param name="routes">List if routes in the train system</param> /// <param name="container">A reference object that we store the scenario data in</param> /// <param name="outerLoop">A boolean that helps us determine what layer of the method we are in</param> private void TraverseRouteScenarios(List <RouteDomainItem> routes, ref RouteScenarioContainer container, bool outerLoop) { foreach (var route in routes) { //if we are in the outer loop and the starting point provided matches the starting point of the route then we need to create a new passenger instance if (outerLoop && route.StartingLocation.CompareTo(container.StartingLocation) == 0) { RoutePassenger passenger = new RoutePassenger() { TravelingToward = route.Destination, DistanceTraveled = route.Distance, Stops = new LinkedList <char>(), RouteMap = new LinkedList <char>(), }; //we use the route map to keep track of everywhere the passenger has been passenger.RouteMap.AddLast(route.StartingLocation); passenger.RouteMap.AddLast(route.Destination); //we use the stops to map everywhere the passenger has arrived passenger.Stops.AddLast(route.Destination); //we create a hash to have an easy way to identify this passenger passenger.SetHash(); container.Passengers.Add(passenger); //We created our passenger, now lets recursively determine how many places he can possibly go in the specified distance TraverseRouteScenarios(routes, ref container, false); }//If we are in a inner loop we can examine our passengers and see if they have divergent options else { for (var i = 0; i < container.Passengers.Count(); i++) { //if the upcoming route is where this passenger is traveling to if (container.Passengers[i].TravelingToward.CompareTo(route.StartingLocation) == 0) { //since we need to preserve scenario data we clone our passenger inorder to create a new instance for tracking purposes var clone = container.Passengers[i].Clone(); clone.Stops.AddLast(route.Destination); clone.RouteMap.AddLast(route.Destination); //since this passenger is divergent from the passenger that may have stopped we will create a new unique identifier clone.SetHash(); clone.DistanceTraveled += route.Distance; clone.TravelingToward = route.Destination; //if we dont have a max distance traveled this passenger would travel forever and probably starve to death //also we need to make sure this clone does not already exist in this universe otherwise we end up with duplicate data //this is why we generated unique identifier with the hash function if (clone.DistanceTraveled < container.MaxDistance && !container.Passengers.Any(m => string.Compare(m.Hash, clone.Hash, true) == 0)) { container.Passengers.Add(clone); //lets traverse all the new possibilities with this new clone TraverseRouteScenarios(routes, ref container, false); } } } } } }
/// <summary> /// Get the number of route variations with the same start and end point /// </summary> /// <param name="start">Starting Platform</param> /// <param name="end">Destination Platform</param> /// <param name="count">Stop Count</param> /// <exception cref="RouteNotFoundException" /// <param name="maxDistance">Depth parameter for graph algorithm</param> /// <returns>Number of stops with equal count between specified platforms</returns> public int GetNumberOfStopsWithEqualCount(char start, char end, int count, int maxDistance) { var routes = _routeRepository.GetAll(); var routeDomainItems = GetRouteDomainItemsForData(routes); RouteScenarioContainer container = new RouteScenarioContainer(start, maxDistance); TraverseRouteScenarios(routeDomainItems, ref container, true); if (container.Passengers.Any()) { return(container.Passengers.Where(m => m.RouteMap.First().CompareTo(start) == 0 && m.RouteMap.Last().CompareTo(end) == 0 && m.Stops.Count() == count).Count()); } throw new RouteNotFoundException(); }
/// <summary> /// Get the distance between any number of linked platforms in the train system /// </summary> /// <param name="plannedRoute">A linked list of route points</param> /// <param name="maxDistance">Depth parameter for graph algorithm</param> /// <exception cref="RouteNotFoundException" /// <returns></returns> public int GetSpeicificRoutesDistance(LinkedList <char> plannedRoute, int maxDistance) { var routes = _routeRepository.GetAll(); var routeDomainItems = GetRouteDomainItemsForData(routes); RouteScenarioContainer container = new RouteScenarioContainer(plannedRoute.First(), maxDistance); TraverseRouteScenarios(routeDomainItems, ref container, true); if (container.Passengers.Any()) { foreach (var passenger in container.Passengers) { if (plannedRoute.SequenceEqual(passenger.RouteMap)) { return(passenger.DistanceTraveled); } } } throw new RouteNotFoundException(); }
/// <summary> /// Gets the count of routes that start and finish at the same train station /// </summary> /// <param name="start">Starting Platform</param> /// <param name="maxStop">Maximum number of platoforms on this route</param> /// <param name="maxDistance">Depth parameter for graph algorithm</param> /// <exception cref="RouteNotFoundException" /// <returns>number of routes that loop back to starting point</returns> public int GetCountOfRoutesThatLoop(char start, int maxStop, int maxDistance) { var routes = _routeRepository.GetAll(); var routeDomainItems = GetRouteDomainItemsForData(routes); RouteScenarioContainer container = new RouteScenarioContainer(start, maxDistance); TraverseRouteScenarios(routeDomainItems, ref container, true); if (container.Passengers.Any()) { if (maxStop > 0) { return(container.Passengers.Where(m => m.RouteMap.First().CompareTo(start) == 0 && m.RouteMap.Last().CompareTo(start) == 0 && m.Stops.Count() <= maxStop).Count()); } else { return(container.Passengers.Count()); } } throw new RouteNotFoundException(); }