Skip to content

Commit 7293280

Browse files
author
Jegors Cemisovs
committed
Add sample Groovy application
1 parent f1e39cc commit 7293280

File tree

15 files changed

+125
-73
lines changed

15 files changed

+125
-73
lines changed

Diff for: .idea/gradle.xml

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: algorithm/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
plugins {
2-
// id 'groovy'
2+
id 'groovy'
33
id 'java-library'
44
id 'maven-publish'
55
}

Diff for: algorithm/src/main/java/lv/id/jc/algorithm/graph/Graph.java

+15-15
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,22 @@
1414
@FunctionalInterface
1515
public interface Graph<T> {
1616
/**
17-
* The schema of this graph.
17+
* Creates a Graph object by given schema.
18+
* <p>
19+
* In a graph schema, each vertex is assigned an edge map.
20+
* If the vertex has no edges, then it should be assigned an empty map.
1821
*
22+
* @param schema of the graph
23+
* @param <T> the type of vertex in this graph
24+
* @return graph object with given schema
25+
*/
26+
static <T> Graph<T> of(Map<T, Map<T, Number>> schema) {
27+
return () -> schema;
28+
}
29+
30+
/**
31+
* The schema of this graph.
32+
* <p>
1933
* In a graph schema, each vertex is assigned an edge map.
2034
* If the vertex has no edges, then it should be assigned an empty map.
2135
*
@@ -54,18 +68,4 @@ default double getDistance(List<T> path) {
5468
.mapToDouble(Number::doubleValue)
5569
.sum();
5670
}
57-
58-
/**
59-
* Creates a Graph object by given schema.
60-
*
61-
* In a graph schema, each vertex is assigned an edge map.
62-
* If the vertex has no edges, then it should be assigned an empty map.
63-
*
64-
* @param schema of the graph
65-
* @param <T> the type of vertex in this graph
66-
* @return graph object with given schema
67-
*/
68-
static <T> Graph<T> of(Map<T, Map<T, Number>> schema) {
69-
return () -> schema;
70-
}
7171
}

Diff for: algorithm/src/main/java/lv/id/jc/algorithm/graph/SearchAlgorithm.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
/**
66
* A functional interface for graph search algorithm
77
*
8-
* @author Jegors Čemisovs
98
* @param <T> the type of vertex
9+
* @author Jegors Čemisovs
1010
* @since 1.0
1111
*/
1212
@FunctionalInterface
1313
public interface SearchAlgorithm<T> {
1414
/**
1515
* Find the path from the source node to the target
1616
*
17-
* @param graph The graph in which we search for the path
17+
* @param graph The graph in which we search for the path
1818
* @param source Search starting point identifier
1919
* @param target Search finish point identifier
2020
* @return Path found or empty list if path cannot be found

Diff for: algorithm/src/test/groovy/lv/id/jc/graph/BreadthFirstSearchSpec.groovy renamed to algorithm/src/test/groovy/BreadthFirstSearchSpec.groovy

+13-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
package lv.id.jc.graph
2-
31
import lv.id.jc.algorithm.graph.BreadthFirstSearch
42
import lv.id.jc.algorithm.graph.Graph
53
import spock.lang.*
@@ -14,20 +12,20 @@ class BreadthFirstSearchSpec extends Specification {
1412
def algorithm = new BreadthFirstSearch()
1513

1614
def 'should find a route for simple graph'() {
17-
given: 'A simple graph'
15+
given:
1816
def graph = Graph.of([
1917
A: [B: 7, C: 2],
2018
B: [A: 3, C: 5],
2119
C: [A: 1, B: 3]
2220
])
2321

24-
when: 'we use Breadth First Search algorithm to find a path'
22+
when:
2523
def path = algorithm.findPath(graph, source, target)
2624

27-
then: 'we get the shortest path'
25+
then:
2826
path == shortest
2927

30-
and: 'the distance calculated correctly'
28+
and:
3129
graph.getDistance(path) == time as double
3230

3331
where:
@@ -39,7 +37,7 @@ class BreadthFirstSearchSpec extends Specification {
3937
}
4038

4139
def 'should find a route for complex graph'() {
42-
given: 'A complex graph'
40+
given:
4341
def graph = Graph.of([
4442
A: [B: 1],
4543
B: [A: 1, D: 1],
@@ -48,13 +46,13 @@ class BreadthFirstSearchSpec extends Specification {
4846
E: [F: 1],
4947
F: [D: 1, E: 1]])
5048

51-
when: 'we use Breadth First Search algorithm to find a path'
49+
when:
5250
def path = algorithm.findPath(graph, source, target)
5351

54-
then: 'we get the shortest path'
52+
then:
5553
path == shortest
5654

57-
and: 'the distance calculated correctly'
55+
and:
5856
graph.getDistance(path) == time as double
5957

6058
where:
@@ -72,24 +70,24 @@ class BreadthFirstSearchSpec extends Specification {
7270
}
7371

7472
def 'should thrown NPE path for an empty graph'() {
75-
given: 'an empty graph'
73+
given:
7674
def graph = Graph.of([:])
7775

78-
when: "we use Dijkstra's algorithm to find a path"
76+
when:
7977
algorithm.findPath(graph, 'A', 'B')
8078

81-
then: 'the exception was thrown'
79+
then:
8280
thrown NullPointerException
8381
}
8482

8583
def "should return an empty path if can't find a route"() {
8684
given: 'a simple graph with no edge between nodes'
8785
def graph = Graph.of([A: [:], B: [:]])
8886

89-
when: 'we use Breadth First Search algorithm to find a path'
87+
when:
9088
def path = algorithm.findPath(graph, 'A', 'B')
9189

92-
then: 'we get an empty path'
90+
then:
9391
path == []
9492
}
9593
}

Diff for: algorithm/src/test/groovy/lv/id/jc/graph/DijkstrasAlgorithmSpec.groovy renamed to algorithm/src/test/groovy/DijkstrasAlgorithmSpec.groovy

+17-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
package lv.id.jc.graph
2-
31
import lv.id.jc.algorithm.graph.DijkstrasAlgorithm
42
import lv.id.jc.algorithm.graph.Graph
53
import spock.lang.*
@@ -12,20 +10,20 @@ class DijkstrasAlgorithmSpec extends Specification {
1210
def algorithm = new DijkstrasAlgorithm()
1311

1412
def 'should find a route for a simple graph'() {
15-
given: 'A simple graph'
13+
given:
1614
def graph = Graph.of([
1715
A: [B: 7, C: 2],
1816
B: [A: 3, C: 5],
1917
C: [A: 1, B: 3]
2018
])
2119

22-
when: "we use Dijkstra's algorithm to find a path"
20+
when:
2321
def path = algorithm.findPath(graph, source, target)
2422

25-
then: 'we get the fastest way'
23+
then:
2624
path == fastest
2725

28-
and: 'the distance calculated correctly'
26+
and:
2927
graph.getDistance(path) == time as double
3028

3129
where:
@@ -37,7 +35,7 @@ class DijkstrasAlgorithmSpec extends Specification {
3735
}
3836

3937
def 'should find a route for a medium graph'() {
40-
given: 'A medium graph'
38+
given:
4139
def graph = Graph.of([
4240
A: [B: 5],
4341
B: [A: 5, C: 10],
@@ -46,13 +44,13 @@ class DijkstrasAlgorithmSpec extends Specification {
4644
E: [B: 5]
4745
])
4846

49-
when: "we use Dijkstra's algorithm to find a path"
47+
when:
5048
def path = algorithm.findPath(graph, source, target)
5149

52-
then: 'we get the fastest way'
50+
then:
5351
path == fastest
5452

55-
and: 'the distance calculated correctly'
53+
and:
5654
graph.getDistance(path) == time as double
5755

5856
where:
@@ -66,7 +64,7 @@ class DijkstrasAlgorithmSpec extends Specification {
6664
}
6765

6866
def 'should find a route for a complex graph'() {
69-
given: 'A complex graph'
67+
given:
7068
def graph = Graph.of([
7169
A: [B: 5, H: 2],
7270
B: [A: 5, C: 7],
@@ -78,13 +76,13 @@ class DijkstrasAlgorithmSpec extends Specification {
7876
H: [G: 3]
7977
])
8078

81-
when: "we use Dijkstra's algorithm to find a path"
79+
when:
8280
def path = algorithm.findPath(graph, source, target)
8381

84-
then: 'we get the fastest way'
82+
then:
8583
path == fastest
8684

87-
and: 'the distance calculated correctly'
85+
and:
8886
graph.getDistance(path) == time as double
8987

9088
where:
@@ -104,24 +102,24 @@ class DijkstrasAlgorithmSpec extends Specification {
104102
}
105103

106104
def 'should thrown NPE for an empty graph'() {
107-
given: 'an empty graph'
105+
given:
108106
def graph = Graph.of([:])
109107

110-
when: "we use Dijkstra's algorithm to find a path"
108+
when:
111109
algorithm.findPath(graph, 'A', 'B')
112110

113-
then: 'the exception was thrown'
111+
then:
114112
thrown NullPointerException
115113
}
116114

117115
def "should return an empty path if can't find a route"() {
118116
given: 'a simple graph with no edge between nodes'
119117
def graph = Graph.of([A: [:], B: [:]])
120118

121-
when: "we use Dijkstra's algorithm to find a path"
119+
when:
122120
def path = algorithm.findPath(graph, 'A', 'B')
123121

124-
then: 'we get an empty path'
122+
then:
125123
path == []
126124
}
127125
}

Diff for: algorithm/src/test/groovy/lv/id/jc/graph/GraphSpec.groovy renamed to algorithm/src/test/groovy/GraphSpec.groovy

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
package lv.id.jc.graph
2-
31
import lv.id.jc.algorithm.graph.Graph
42
import spock.lang.Narrative
53
import spock.lang.Specification

Diff for: algorithm/src/test/groovy/lv/id/jc/graph/SearchAlgorithmSpec.groovy renamed to algorithm/src/test/groovy/SearchAlgorithmSpec.groovy

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
package lv.id.jc.graph
2-
31
import lv.id.jc.algorithm.graph.BreadthFirstSearch
42
import lv.id.jc.algorithm.graph.DijkstrasAlgorithm
53
import lv.id.jc.algorithm.graph.Graph
@@ -16,7 +14,7 @@ class SearchAlgorithmSpec extends Specification {
1614
def dijkstras = new DijkstrasAlgorithm()
1715

1816
def 'should find a route for a complex graph'() {
19-
given: 'A complex graph sample'
17+
given:
2018
def graph = Graph.of([
2119
A: [B: 5, H: 2],
2220
B: [A: 5, C: 7],
@@ -28,19 +26,19 @@ class SearchAlgorithmSpec extends Specification {
2826
H: [G: 3]
2927
])
3028

31-
when: 'we use Breadth First Search algorithm for the first route'
29+
when:
3230
def routeOne = bfsAlgorithm.findPath(graph, source, target)
3331

34-
and: 'we use Dijkstras algorithm for the second route'
32+
and:
3533
def routeTwo = dijkstras.findPath(graph, source, target)
3634

37-
then: "the first route is the shortest"
35+
then:
3836
routeOne == shortest
3937

40-
and: 'the second route is the fastest'
38+
and:
4139
routeTwo == fastest
4240

43-
and: 'the distance calculated correctly'
41+
and:
4442
graph.getDistance(routeOne) == d1 as double
4543
graph.getDistance(routeTwo) == d2 as double
4644

Diff for: application/src/main/java/module-info.java

-4
This file was deleted.

Diff for: sample-groovy/build.gradle

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
plugins {
2+
id 'groovy'
3+
}
4+
5+
java {
6+
sourceCompatibility = JavaVersion.VERSION_17
7+
}
8+
9+
repositories {
10+
mavenCentral()
11+
}
12+
13+
dependencies {
14+
implementation 'org.codehaus.groovy:groovy-all:3.0.8'
15+
implementation project(':algorithm')
16+
}
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package lv.id.jc.sample
2+
3+
import lv.id.jc.algorithm.graph.BreadthFirstSearch
4+
import lv.id.jc.algorithm.graph.DijkstrasAlgorithm
5+
import lv.id.jc.algorithm.graph.Graph
6+
7+
def complexGraph = Graph.of([
8+
A: [B: 5, H: 2],
9+
B: [A: 5, C: 7],
10+
C: [B: 7, D: 3, G: 4],
11+
D: [C: 20, E: 4],
12+
E: [F: 5],
13+
F: [G: 6],
14+
G: [C: 4],
15+
H: [G: 3]
16+
])
17+
18+
def app = new SampleApp(complexGraph)
19+
20+
app.printRoute('D', 'C');
21+
app.printRoute('A', 'G');
22+
app.printRoute('D', 'H');
23+
24+
class SampleApp {
25+
final fastest = new DijkstrasAlgorithm();
26+
final shortest = new BreadthFirstSearch();
27+
final graph
28+
29+
SampleApp(graph) {
30+
this.graph = graph
31+
}
32+
33+
def printRoute(source, target) {
34+
var routeOne = shortest.findPath(graph, source, target);
35+
var routeTwo = fastest.findPath(graph, source, target);
36+
37+
println """Find the path from $source to $target
38+
- the shortest take ${graph.getDistance(routeOne)} min and the path is ${routeOne}
39+
- the fastest take ${graph.getDistance(routeTwo)} min and the path is ${routeTwo}
40+
"""
41+
}
42+
43+
}

0 commit comments

Comments
 (0)