kruskal

Ruby code posted by AndrewCap
created at 18 Dec 23:48

Edit | Back
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
require 'pp'
require 'benchmark'

def file 
  @file ||= File.readlines("edges.txt")
end

def has_cycles(edge)
  node_one, node_two = edge[:from], edge[:to]  
  @minimum_spanning_tree.each { |x| x[:explored] = false }
  cycle_between(node_one, node_two, @minimum_spanning_tree.dup)
end

def cycle_between(one, two, edges)
  adjacent_edges = edges.select { |edge| edge[:to] == one || edge[:from] == one}  
  return false if adjacent_edges.empty?
  adjacent_edges.reject {|edge| edge[:explored] }.each do |edge|
    edge[:explored] = true
    other_node = (edge[:from] == one) ? edge[:to] : edge[:from]
    return true if other_node == two || cycle_between(other_node, two, edges)
  end
  false
end

@minimum_spanning_tree = []

edges = file.drop(1).map { |x| x.gsub(/\n/, "").split(" ").map(&:to_i) }.
                     map { |one, two, weight| { :from => one, :to => two, :weight => weight}}.
                     sort_by { |x| x[:weight]}
  
Benchmark.bm (10){ |x|
x.report("Kruskal time: "){
edges.each do |edge|
  @minimum_spanning_tree << edge unless has_cycles edge
end
}
puts

}
puts "MST:" 
pp @minimum_spanning_tree
puts
puts "Cost: #{@minimum_spanning_tree.inject(0) { |acc, x| acc + x[:weight]}}"
1.22 KB in 4 ms with coderay