Class: Trainworks::GraphAlgorithm
- Inherits:
-
Object
- Object
- Trainworks::GraphAlgorithm
- Defined in:
- lib/trainworks/graph_algorithm.rb
Overview
GraphAlgorithm is used to calculate direct distances, shortest path and other paths between nodes. It assumes graph is a hash of adjacencies of a directed-positively-weighted-possibly-cyclic-graph
Defined Under Namespace
Classes: NoSuchRoute
Instance Method Summary collapse
- #distance(cities) ⇒ Number, String
-
#initialize(graph) ⇒ GraphAlgorithm
constructor
A new instance of GraphAlgorithm.
-
#shortest_distance(from:, to:) ⇒ Number
It calls #trips to find all paths between the starting point and the goal and returns the shortest distance found.
-
#trips(from:, to:, current_distance: 0, current_path: [from], all_paths: {}) ⇒ Hash
All possible trips from the starting point to the goal without repeating loops.
-
#trips_with_exact_stops(from:, to:, stops:) ⇒ Array<Array>
it calls #trips_with_max_stops and filter out the trips that don't have the exact number of stops as
stops. -
#trips_with_max_distance(from:, to:, max_distance:, total_paths: [from], solutions: {}, current_distance: 0) ⇒ Array<Array>
Since we calculate the distance by adding up the distances between the nodes, the edges must have positive distances otherwise it's not garateed the algorithm will reach a stop.
-
#trips_with_max_stops(from:, to:, stops:, total_paths: [from], solutions: []) ⇒ Array<Array>
All possible trips from the starting point to the goal with maximum stops equal to
stops.
Constructor Details
#initialize(graph) ⇒ GraphAlgorithm
Returns a new instance of GraphAlgorithm.
14 15 16 |
# File 'lib/trainworks/graph_algorithm.rb', line 14 def initialize(graph) @graph = graph end |
Instance Method Details
#distance(cities) ⇒ Number, String
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/trainworks/graph_algorithm.rb', line 23 def distance(cities) distance = 0 begin cities.each_cons(2) do |(from, to)| distance += go(from: from, to: to) end rescue NoSuchRoute => e distance = e.to_s end distance end |
#shortest_distance(from:, to:) ⇒ Number
It calls #trips to find all paths between the starting point and the goal and returns
the shortest distance found. If there's no path between from and to it raises NoSuchRoute
114 115 116 117 118 |
# File 'lib/trainworks/graph_algorithm.rb', line 114 def shortest_distance(from:, to:) shortest_distance = trips(from: from, to: to).values.min raise NoSuchRoute if shortest_distance.nil? shortest_distance end |
#trips(from:, to:, current_distance: 0, current_path: [from], all_paths: {}) ⇒ Hash
Returns all possible trips from the starting point to the goal without repeating loops.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/trainworks/graph_algorithm.rb', line 90 def trips(from:, to:, current_distance: 0, current_path: [from], all_paths: {}) routes(from).map do |city, _paths| next_current_path = [*current_path, city] next_current_distance = current_distance + go(from: from, to: city) all_paths[next_current_path] = next_current_distance if arrived?(city, to) next if arrived?(city, to) || already_visited?(next_current_path, city) trips( from: city, to: to, current_distance: next_current_distance, current_path: next_current_path, all_paths: all_paths ) end all_paths end |
#trips_with_exact_stops(from:, to:, stops:) ⇒ Array<Array>
it calls #trips_with_max_stops and filter out the trips that don't have the exact number of stops as stops
56 57 58 59 60 61 |
# File 'lib/trainworks/graph_algorithm.rb', line 56 def trips_with_exact_stops(from:, to:, stops:) total_path_size = stops + 1 # a path includes the stops plus the origin trips_with_max_stops(from: from, to: to, stops: stops).select do |path| path.size == total_path_size end end |
#trips_with_max_distance(from:, to:, max_distance:, total_paths: [from], solutions: {}, current_distance: 0) ⇒ Array<Array>
Since we calculate the distance by adding up the distances between the nodes, the edges must have positive distances otherwise it's not garateed the algorithm will reach a stop.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/trainworks/graph_algorithm.rb', line 69 def trips_with_max_distance(from:, to:, max_distance:, total_paths: [from], solutions: {}, current_distance: 0) routes(from).map do |city, _paths| next_current_distance = current_distance + go(from: from, to: city) return solutions.keys if next_current_distance >= max_distance next_total_paths = [*total_paths, city] solutions[next_total_paths] = next_current_distance if arrived?(city, to) trips_with_max_distance( from: city, to: to, max_distance: max_distance, total_paths: next_total_paths, solutions: solutions, current_distance: next_current_distance ) end solutions.keys end |
#trips_with_max_stops(from:, to:, stops:, total_paths: [from], solutions: []) ⇒ Array<Array>
Returns all possible trips from the starting point to the goal with maximum stops equal to stops.
40 41 42 43 44 45 46 47 48 |
# File 'lib/trainworks/graph_algorithm.rb', line 40 def trips_with_max_stops(from:, to:, stops:, total_paths: [from], solutions: []) routes(from).map do |city, _paths| return solutions if 0 >= stops next_total_paths = [*total_paths, city] solutions.push(next_total_paths) if arrived?(city, to) trips_with_max_stops(from: city, to: to, stops: stops - 1, total_paths: next_total_paths, solutions: solutions) end solutions end |