-
Notifications
You must be signed in to change notification settings - Fork 267
/
Dijkstra.scala
62 lines (50 loc) · 1.83 KB
/
Dijkstra.scala
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
import scala.annotation.tailrec
trait Path {
def edges: Seq[Edge]
}
case class ExistingPath(edges: Seq[Edge]) extends Path
object EmptyPath extends Path {
override def edges: Seq[Edge] = Seq.empty
}
case class Vertex(id: String)
case class Edge(from: Vertex, to: Vertex, distance: Int)
case class Graph(edges: List[Edge]) {
implicit object EdgesOrdering extends Ordering[Edge] {
def compare(a: Edge, b: Edge) = a.distance compare b.distance
}
@tailrec
final def dijkstra(start: Vertex, pathComposition: Path = EmptyPath): Path = {
val startEdges: Seq[Edge] = edges.filter(_.from == start).sorted
val smallestDistance: Option[Edge] = startEdges
.filter(e => !pathComposition.edges.map(_.from).contains(e.to))
.headOption
smallestDistance match {
case Some(distance) =>
dijkstra(
distance.to,
ExistingPath(edges = pathComposition.edges.appended(distance))
)
case None => pathComposition
}
}
}
object Main extends App {
val startA: Vertex = Vertex("A")
val graph: Graph = Graph(
edges = List(
Edge(from = Vertex("A"), to = Vertex("B"), distance = 1),
Edge(from = Vertex("A"), to = Vertex("C"), distance = 4),
Edge(from = Vertex("B"), to = Vertex("A"), distance = 1),
Edge(from = Vertex("B"), to = Vertex("C"), distance = 2),
Edge(from = Vertex("B"), to = Vertex("D"), distance = 5),
Edge(from = Vertex("C"), to = Vertex("A"), distance = 4),
Edge(from = Vertex("C"), to = Vertex("B"), distance = 2),
Edge(from = Vertex("C"), to = Vertex("D"), distance = 1),
Edge(from = Vertex("D"), to = Vertex("B"), distance = 5),
Edge(from = Vertex("D"), to = Vertex("C"), distance = 1)
)
)
val result: Path = graph.dijkstra(start = startA)
println("Calculating path...")
println(s"Result: ${result.edges}")
}