Guest User

Untitled

a guest
Apr 22nd, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.45 KB | None | 0 0
  1. require 'set'
  2.  
  3. class ClosedCircuit
  4. Infinity = 1/0.0
  5.  
  6. def initialize(input, source, dest)
  7. @graph = GraphParser.parse(input)
  8. @source = source
  9. @dest = dest
  10. end
  11.  
  12. # Substract the edges of the shortest path from the edges of the graph
  13. def redundant_edges
  14. redun = @graph.edge_set - edges_of_shortest_path
  15.  
  16. # Return the redundant edges in the required format
  17. redun.sort.map {|e| [ e.vertices.sort.map {|v| v.name }, e.weight].flatten }
  18. end
  19.  
  20. def edges_of_shortest_path
  21. edges_from_path( shortest_path )
  22. end
  23.  
  24. # Use Dijkstra's algorithm to find the shortest path
  25. def shortest_path
  26. dist, previous = Hash.new(Infinity), {}
  27. dist[@source] = 0.0
  28. queue = @graph.vertex_set.dup
  29.  
  30. until queue.empty?
  31. u = queue.min { |a,b| dist[a.name] <=> dist[b.name] }
  32. break if dist[u.name].infinite?
  33. queue.delete(u)
  34.  
  35. u.each_edge do |e, v|
  36. alt = dist[u.name] + e.weight
  37. if alt < dist[v.name]
  38. dist[v.name] = alt
  39. previous[v.name] = u.name
  40. end
  41. end
  42. end
  43.  
  44. path = []
  45. u = @dest
  46. until previous[u].nil?
  47. path.unshift(u)
  48. u = previous[u]
  49. end
  50.  
  51. path.unshift(@source)
  52. end
  53.  
  54. def edges_from_path(path)
  55. edges = []
  56. each_pair_in_path(path) do |curr, nxt|
  57. edges << @graph.vertices[curr].edge_to( @graph.vertices[nxt] )
  58. end
  59. edges.to_set
  60. end
  61.  
  62. # Iterate over each pair of vertices in the path
  63. def each_pair_in_path(path)
  64. path.each_with_index do |name, i|
  65. yield name, path[i+1] unless path[i+1].nil?
  66. end
  67. end
  68.  
  69. class Graph
  70. attr_reader :vertex_set, :edge_set
  71.  
  72. def initialize
  73. @vertex_set = Set.new
  74. @edge_set = Set.new
  75.  
  76. yield self if block_given?
  77. end
  78.  
  79. def vertices
  80. @vertices ||= Hash.new { |hash, key| hash[key] = Vertex.new(key) }
  81. end
  82.  
  83. def add_edge(u,v,w)
  84. u, v = vertices[u], vertices[v] # Create vertices
  85. e = Edge.new(u,v,w) # Create the edge
  86. @edge_set.add(e) # Add edge to edge set
  87.  
  88. [u,v].each do |x|
  89. x.edges.add(e) # Add edge to both vertex
  90. @vertex_set.add(x) # Add vertex to vertex set
  91. end
  92. end
  93. end
  94.  
  95. class Vertex < Struct.new(:name)
  96. def edges
  97. @edges ||= Set.new
  98. end
  99.  
  100. def each_edge
  101. edges.each do |e|
  102. other = e.vertices.find { |v| v != self }
  103. yield e, other
  104. end
  105. end
  106.  
  107. def edge_to(other)
  108. edges.find { |e| e.vertices.include?(other) }
  109. end
  110.  
  111. def <=>(other)
  112. name <=> other.name
  113. end
  114. end
  115.  
  116. class Edge
  117. attr_reader :vertices, :weight
  118. def initialize(u,v,w)
  119. @vertices = Set[u,v]
  120. @weight = w.to_i
  121. end
  122.  
  123. def name
  124. vertices.sort.map { |v| v.name }.join
  125. end
  126.  
  127. def <=>(other)
  128. name <=> other.name
  129. end
  130. end
  131.  
  132. class GraphParser
  133. def self.parse(input)
  134. Graph.new do |g|
  135. input.each_line { |l| g.add_edge(*l.split) }
  136. end
  137. end
  138. end
  139. end
  140.  
  141. # Prove that it works
  142. if $0 == __FILE__
  143. require "test/unit"
  144. class TestShortCircuit < Test::Unit::TestCase
  145. def test_short_circuit
  146. expected_result = [
  147. [ 'A', 'B', 50 ],
  148. [ 'B', 'C', 250],
  149. [ 'B', 'E', 250],
  150. [ 'C', 'E', 350],
  151. [ 'D', 'F', 400],
  152. [ 'E', 'G', 200],
  153. ]
  154.  
  155. assert_equal expected_result, ClosedCircuit.new(DATA.read, "A", "G").redundant_edges
  156. end
  157. end
  158. end
  159.  
  160. __END__
  161. A B 50
  162. A D 150
  163. B C 250
  164. B E 250
  165. C E 350
  166. C D 50
  167. C F 100
  168. D F 400
  169. E G 200
  170. F G 100
Add Comment
Please, Sign In to add comment