Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.
My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#require 'test/unit' # Normal array to_string printout is hard to read. Put some spaces and add # leading/trailing square brackets '[' ']' to make the array printout a bit prettier str = "[" self.each {|e| str << " "} str << " ]" end end test_array = [] test_array << [ ["A B 50", "A D 150", "B C 250", "B E 250", "C E 350", "F G 100", "D F 400", "F C 100", "E G 200", "C D 50"], '[ A B 50 ] [ B C 250 ] [ B E 250 ] [ C E 350 ] [ D F 400 ] [ E G 200 ] ' ] test_array << [ ["A B 1", "A D 3", "B C 3", "B E 1", "E C 1", "E G 4", "F G 1", "F D 3", "F C 1", "C D 3"], '[ A D 3 ] [ B C 3 ] [ E G 4 ] [ F D 3 ] [ C D 3 ]' ] test_array << [ ["A B 2", "A C 6", "B G 7", "C G 3", "B C 3"], '[ A C 6 ] [ B G 7 ]' ] test_array << [ ["A B 3", "A C 2", "B G 3", "C G 2", "B C 1"], '[ A B 3 ] [ B G 3 ] [ B C 1 ]' ] test_array.each do | e | puts "For " puts "Expected Answer " puts "Actual Answer \n\n" end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# A segment is a unique entity in a network - identified by a named # node on each end and a resistance between the two nodes attr_accessor :ohms, :node1, :node2 # "other end" given one end (self.node2 == src_node) ? self.node1 : self.node2 end self.node1 = nd1; self.node2 = nd2; self.ohms = res end # Convert to an array [self.node1.name, self.node2.name, self.ohms] end end # A unique 'named' entity in the network. It has an array of segments # which effectively document what other nodes are linked to this one attr_accessor :name, :segments # For this node (could be any in the network), compute the shortest path # to 'ground'. For this algorithm, we need to know what nodes have already # been visited because we don't want to "turn back". So we stop tracing # when we hit 'ground' or a node that has already been visited unless self == ground # really large number guaranteed to be larger than the resistance of a particular segment ohms = Math.exp(999) path = [] # for each segment connected to this node... self.segments.each do |s| tar_node = s.target_node(self) unless visited.include?(tar_node) visited_copy = visited.clone << self # recursively ask target node to compute its shortest path result = tar_node.shortest_path(visited_copy, ground) # if the result path is shorter than our current shortest path then... if ((result[:ohms] + s.ohms) < ohms) # the new shortest resistance value = target node's shortest resistance # plus the resistance of the segment connecting to that node ohms = result[:ohms] + s.ohms # record the shortest path also. it is an array and we need to add the # segment at the 'head' of the array path = result[:path].unshift(s) end end end # return the shortest path (segment array) and value of total resistance for that path {:path => path, :ohms => ohms} else # self == ground # for ground, we have nothing interesting to return - we are already at th end {:path => [], :ohms => 0} end end # add a segment to this node self.segments << seg end self.name = name self.segments = [] end end # Utility class (probably didn't need a whole separate class just for holding one method) # Compute the shortest path and by 'subtraction' compute the obsolete segments in the # network. Algorithm needs to be know the source of electricity and the end point (ground) nodes = {} segments = [] # for each segment definition ... seg_defs.each do |seg_def| seg = seg_def.split(' ') # figure out the two node names for each end of the segment src_name = seg[0].to_sym tar_name = seg[1].to_sym # have we already seen a node with that name before - if so get it - otherwise create a new one src_node = (nodes[src_name] == nil) ? nodes[src_name] = Node.new(src_name) : nodes[src_name] tar_node = (nodes[tar_name] == nil) ? nodes[tar_name] = Node.new(tar_name) : nodes[tar_name] # create a new segment with the two nodes at each end and the resistance value seg = Segment.new(src_node, tar_node, seg[2].to_i) src_node << seg tar_node << seg # collect all unique segments into this variable segments << seg end source_node = nodes[source.to_sym] ground_node = nodes[ground.to_sym] # compute shortest path result = source_node.shortest_path([], ground_node) path = result[:path] # eliminate the shortest path to get to obsolete segments path.each {|e| segments.delete(e)} # convert that to array because the assignment asks for an array of arrays segments.collect! {|e| e.to_a} segments end end |