blob: 63e7f0324ca7153fe9f8f43117a95813438606bb [file] [log] [blame]
class Edge {
Integer v1
Integer v2
Integer weight
Edge(Integer v1, Integer v2, Integer w) {
this.v1 = v1
this.v2 = v2
this.weight = w
}
boolean contains(Integer v) { v1 == v || v2 == v }
Integer otherThan(Integer v) { v1 == v ? v2 : v1 }
}
class Graph {
List<Integer> V
Collection<Edge> E
// Dumbest implementation
List<Integer> getIncident(Integer v) { E.findAll{ it.contains(v) }.collect{ it.otherThan(v) } }
Edge findEdge(Integer v1, Integer v2) { E.find{ it.contains(v1) && it.contains(v2) } }
Number weight(Integer v1, Integer v2) { findEdge(v1, v2)?.weight ?: Double.POSITIVE_INFINITY }
}
Collection<Edge> prim(Graph G) {
Set<Edge> T = []
Map<Integer, Number> d = [:] + G.V.collect { new MapEntry(it, Double.POSITIVE_INFINITY) }
Map<Integer, Integer> p = [:] + G.V.collect { new MapEntry(it, null) }
d[G.V[0]] = 0
List<Integer> Q = G.V.collect{it}
Q.metaClass.extractMin = { ->
// Dumbest implementation
int minimum = Q.min { d[it] }
int indexOfMinimum = Q.indexOf(minimum) // here Groovy fails to make a shortcut.
return Q.remove(indexOfMinimum)
}
Integer v = Q.extractMin()
while (!Q.isEmpty()) {
G.getIncident(v).each { Integer u ->
if(Q.contains(u) && G.weight(u, v) < d[u]) {
d[u] = G.weight(u, v)
p[u] = v
}
}
v = Q.extractMin()
T << G.findEdge(p[v], v)
}
T
}
void testPrim() {
Set<Edge> expected = [
new Edge(1, 2, 1),
new Edge(2, 3, 1),
new Edge(3, 4, 1),
new Edge(4, 5, 1),
]
Set<Edge> edges = [
new Edge(1, 3, 2),
new Edge(1, 4, 3),
new Edge(1, 5, 2),
new Edge(2, 4, 7),
new Edge(3, 5, 2),
]
Graph G = new Graph(V: 1..5, E: expected + edges)
Set<Edge> T = prim(G)
assert expected.equals(T)
println "it worked!"
}
testPrim()