trackler 2.1.0.0 → 2.1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/connect/description.md +2 -1
- data/common/exercises/crypto-square/canonical-data.json +2 -2
- data/common/exercises/two-bucket/canonical-data.json +27 -1
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/exercises/perfect-numbers/src/example.c +8 -4
- data/tracks/clojure/config.json +5 -0
- data/tracks/clojure/exercises/secret-handshake/project.clj +4 -0
- data/tracks/clojure/exercises/secret-handshake/src/example.clj +19 -0
- data/tracks/clojure/exercises/secret-handshake/test/secret_handshake_test.clj +55 -0
- data/tracks/cpp/.travis.yml +4 -3
- data/tracks/cpp/README.md +1 -1
- data/tracks/cpp/config.json +171 -67
- data/tracks/cpp/docs/ABOUT.md +2 -2
- data/tracks/cpp/docs/INSTALLATION.md +22 -28
- data/tracks/cpp/docs/TESTS.md +1 -1
- data/tracks/cpp/exercises/anagram/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/beer-song/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/binary/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/bob/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/clock/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/clock/clock_test.cpp +188 -64
- data/tracks/cpp/exercises/clock/example.cpp +17 -12
- data/tracks/cpp/exercises/clock/example.h +1 -0
- data/tracks/cpp/exercises/crypto-square/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/difference-of-squares/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/etl/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/etl/etl_test.cpp +5 -5
- data/tracks/cpp/exercises/food-chain/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/gigasecond/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/gigasecond/example.cpp +2 -6
- data/tracks/cpp/exercises/gigasecond/example.h +2 -2
- data/tracks/cpp/exercises/gigasecond/gigasecond_test.cpp +26 -8
- data/tracks/cpp/exercises/grade-school/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/grade-school/grade_school_test.cpp +5 -6
- data/tracks/cpp/exercises/grains/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/hamming/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/hello-world/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/hexadecimal/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/leap/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/meetup/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/meetup/meetup_test.cpp +1 -1
- data/tracks/cpp/exercises/nth-prime/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/nucleotide-count/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/nucleotide-count/nucleotide_count_test.cpp +3 -4
- data/tracks/cpp/exercises/phone-number/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/prime-factors/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/queen-attack/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/raindrops/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/rna-transcription/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/robot-name/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/roman-numerals/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/say/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/scrabble-score/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/series/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/series/series_test.cpp +11 -11
- data/tracks/cpp/exercises/sieve/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/space-age/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/sum-of-multiples/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/triangle/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/trinary/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/word-count/CMakeLists.txt +2 -9
- data/tracks/cpp/exercises/word-count/word_count_test.cpp +14 -15
- data/tracks/go/README.md +27 -13
- data/tracks/go/config.json +1 -0
- data/tracks/go/exercises/connect/.meta/gen.go +1 -3
- data/tracks/go/exercises/connect/cases_test.go +2 -1
- data/tracks/go/exercises/custom-set/.meta/gen.go +122 -101
- data/tracks/go/exercises/custom-set/cases_test.go +13 -4
- data/tracks/go/exercises/custom-set/custom_set_test.go +2 -2
- data/tracks/go/exercises/hamming/.meta/gen.go +1 -3
- data/tracks/go/exercises/hamming/cases_test.go +7 -1
- data/tracks/go/exercises/hamming/example.go +1 -1
- data/tracks/go/exercises/hamming/hamming_test.go +1 -1
- data/tracks/go/exercises/hello-world/{hello_example_test.go → example_helloworld_test.go} +0 -0
- data/tracks/go/exercises/house/house_test.go +8 -8
- data/tracks/go/exercises/meetup/.meta/gen.go +1 -3
- data/tracks/go/exercises/meetup/cases_test.go +2 -1
- data/tracks/go/exercises/palindrome-products/example.go +1 -1
- data/tracks/go/exercises/palindrome-products/palindrome_products_test.go +1 -1
- data/tracks/go/exercises/pascals-triangle/pascals_triangle_test.go +24 -4
- data/tracks/go/exercises/rna-transcription/.meta/gen.go +1 -3
- data/tracks/go/exercises/rna-transcription/cases_test.go +2 -1
- data/tracks/go/exercises/roman-numerals/.meta/gen.go +1 -3
- data/tracks/go/exercises/roman-numerals/cases_test.go +2 -1
- data/tracks/go/exercises/roman-numerals/example.go +1 -1
- data/tracks/go/exercises/transpose/.meta/gen.go +1 -3
- data/tracks/go/exercises/transpose/cases_test.go +2 -1
- data/tracks/go/exercises/transpose/transpose_test.go +5 -0
- data/tracks/go/exercises/word-count/.meta/gen.go +1 -3
- data/tracks/go/exercises/word-count/cases_test.go +2 -1
- data/tracks/go/gen/gen.go +3 -2
- data/tracks/java/config.json +5 -0
- data/tracks/java/exercises/saddle-points/build.gradle +17 -0
- data/tracks/java/exercises/saddle-points/src/example/java/Matrix.java +44 -0
- data/tracks/java/exercises/saddle-points/src/example/java/MatrixCoordinate.java +31 -0
- data/tracks/java/exercises/saddle-points/src/main/java/Matrix.java +5 -0
- data/tracks/java/exercises/saddle-points/src/main/java/MatrixCoordinate.java +31 -0
- data/tracks/java/exercises/saddle-points/src/test/java/MatrixTest.java +82 -0
- data/tracks/java/exercises/settings.gradle +1 -0
- data/tracks/javascript/.travis.yml +3 -1
- data/tracks/javascript/Makefile +2 -8
- data/tracks/javascript/SETUP.md +1 -2
- data/tracks/javascript/docs/INSTALLATION.md +3 -4
- data/tracks/javascript/docs/TESTS.md +14 -26
- data/tracks/javascript/exercises/hamming/example.js +7 -11
- data/tracks/javascript/exercises/hello-world/HINTS.md +3 -3
- data/tracks/javascript/exercises/robot-simulator/example.js +72 -73
- data/tracks/perl6/config.json +5 -0
- data/tracks/perl6/exercises/clock/Clock.pm6 +4 -0
- data/tracks/perl6/exercises/clock/Example.pm6 +12 -0
- data/tracks/perl6/exercises/clock/clock.t +534 -0
- data/tracks/perl6/exercises/clock/example.yaml +16 -0
- data/tracks/perl6/exercises/robot-name/Example.pm +11 -4
- data/tracks/php/exercises/hello-world/hello-world.php +1 -1
- data/tracks/php/exercises/hello-world/hello-world_test.php +1 -11
- data/tracks/php/exercises/robot-name/robot-name_test.php +1 -0
- data/tracks/purescript/config.json +7 -0
- data/tracks/purescript/exercises/largest-series-product/bower.json +16 -0
- data/tracks/purescript/exercises/largest-series-product/examples/src/LargestSeriesProduct.purs +31 -0
- data/tracks/purescript/exercises/largest-series-product/src/LargestSeriesProduct.purs +3 -0
- data/tracks/purescript/exercises/largest-series-product/test/Main.purs +73 -0
- data/tracks/python/exercises/sublist/sublist_test.py +94 -55
- data/tracks/ruby/README.md +38 -25
- data/tracks/ruby/exercises/hamming/example.tt +6 -4
- data/tracks/ruby/exercises/hamming/hamming_test.rb +4 -5
- data/tracks/ruby/exercises/linked-list/linked_list_test.rb +16 -0
- data/tracks/ruby/exercises/luhn/luhn_test.rb +5 -5
- data/tracks/ruby/exercises/ocr-numbers/.meta/.version +1 -0
- data/tracks/ruby/exercises/ocr-numbers/example.rb +42 -61
- data/tracks/ruby/exercises/ocr-numbers/example.tt +21 -0
- data/tracks/ruby/exercises/ocr-numbers/ocr_numbers_test.rb +63 -138
- data/tracks/ruby/lib/generator/exercise_cases.rb +43 -0
- data/tracks/ruby/lib/generator/underscore.rb +9 -0
- data/tracks/ruby/lib/hamming_cases.rb +9 -14
- data/tracks/ruby/lib/luhn_cases.rb +2 -18
- data/tracks/ruby/lib/ocr_numbers_cases.rb +20 -0
- data/tracks/ruby/lib/pig_latin_cases.rb +2 -12
- data/tracks/ruby/test/generator/underscore_test.rb +23 -0
- data/tracks/scala/config.json +316 -316
- metadata +26 -10
- data/tracks/cpp/exercises/etl/require_equal_containers.h +0 -88
- data/tracks/cpp/exercises/grade-school/require_equal_containers.h +0 -88
- data/tracks/cpp/exercises/nucleotide-count/require_equal_containers.h +0 -88
- data/tracks/cpp/exercises/series/require_equal_containers.h +0 -88
- data/tracks/cpp/exercises/word-count/require_equal_containers.h +0 -88
- data/tracks/javascript/exercises/acronym/package.json +0 -12
- data/tracks/javascript/package.json +0 -12
File without changes
|
@@ -19,7 +19,7 @@ const targetTestVersion = 1
|
|
19
19
|
|
20
20
|
var (
|
21
21
|
// song copied from README
|
22
|
-
|
22
|
+
expectedSong = `This is the house that Jack built.
|
23
23
|
|
24
24
|
This is the malt
|
25
25
|
that lay in the house that Jack built.
|
@@ -109,7 +109,7 @@ that killed the rat
|
|
109
109
|
that ate the malt
|
110
110
|
that lay in the house that Jack built.`
|
111
111
|
|
112
|
-
|
112
|
+
expectedVerses = strings.Split(expectedSong, "\n\n")
|
113
113
|
)
|
114
114
|
|
115
115
|
func TestTestVersion(t *testing.T) {
|
@@ -119,26 +119,26 @@ func TestTestVersion(t *testing.T) {
|
|
119
119
|
}
|
120
120
|
|
121
121
|
func TestVerse(t *testing.T) {
|
122
|
-
for v := 0; v < len(
|
123
|
-
if ret := Verse(v + 1); ret !=
|
124
|
-
t.Fatalf("Verse(%d) =\n%q\n want:\n%q", v+1, ret,
|
122
|
+
for v := 0; v < len(expectedVerses); v++ {
|
123
|
+
if ret := Verse(v + 1); ret != expectedVerses[v] {
|
124
|
+
t.Fatalf("Verse(%d) =\n%q\n want:\n%q", v+1, ret, expectedVerses[v])
|
125
125
|
}
|
126
126
|
}
|
127
127
|
}
|
128
128
|
|
129
129
|
func TestSong(t *testing.T) {
|
130
130
|
s := Song()
|
131
|
-
if s ==
|
131
|
+
if s == expectedSong {
|
132
132
|
return
|
133
133
|
}
|
134
134
|
// a little help in locating an error
|
135
135
|
gotStanzas := len(strings.Split(s, "\n\n"))
|
136
|
-
wantStanzas := len(
|
136
|
+
wantStanzas := len(expectedVerses)
|
137
137
|
if wantStanzas != gotStanzas {
|
138
138
|
t.Fatalf("Song() has %d verse(s), want %d verses", gotStanzas, wantStanzas)
|
139
139
|
}
|
140
140
|
got := strings.Split(s, "\n")
|
141
|
-
want := strings.Split(
|
141
|
+
want := strings.Split(expectedSong, "\n")
|
142
142
|
var g, w string
|
143
143
|
var i int
|
144
144
|
for i, w = range want {
|
@@ -47,7 +47,7 @@ func Products(fmin, fmax int) (pmin, pmax Product, err error) {
|
|
47
47
|
}
|
48
48
|
}
|
49
49
|
if len(pmin.Factorizations) == 0 {
|
50
|
-
err = fmt.Errorf("
|
50
|
+
err = fmt.Errorf("no palindromes in range [%d, %d]", fmin, fmax)
|
51
51
|
}
|
52
52
|
return
|
53
53
|
}
|
@@ -38,7 +38,7 @@ var testData = []struct {
|
|
38
38
|
Product{10201, [][2]int{{101, 101}}},
|
39
39
|
Product{906609, [][2]int{{913, 993}}},
|
40
40
|
""},
|
41
|
-
{4, 10, Product{}, Product{}, "
|
41
|
+
{4, 10, Product{}, Product{}, "no palindromes"},
|
42
42
|
{10, 4, Product{}, Product{}, "fmin > fmax"},
|
43
43
|
}
|
44
44
|
|
@@ -8,7 +8,7 @@ import (
|
|
8
8
|
|
9
9
|
const targetTestVersion = 1
|
10
10
|
|
11
|
-
var
|
11
|
+
var triangleTestCases = [][]int{
|
12
12
|
{1},
|
13
13
|
{1, 1},
|
14
14
|
{1, 2, 1},
|
@@ -31,6 +31,8 @@ var t20 = [][]int{
|
|
31
31
|
{1, 19, 171, 969, 3876, 11628, 27132, 50388, 75582, 92378, 92378, 75582, 50388, 27132, 11628, 3876, 969, 171, 19, 1},
|
32
32
|
}
|
33
33
|
|
34
|
+
var testSize = len(triangleTestCases)
|
35
|
+
|
34
36
|
func TestTestVersion(t *testing.T) {
|
35
37
|
if testVersion != targetTestVersion {
|
36
38
|
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
@@ -38,15 +40,15 @@ func TestTestVersion(t *testing.T) {
|
|
38
40
|
}
|
39
41
|
|
40
42
|
func TestTriangle(t *testing.T) {
|
41
|
-
for n := 1; n <=
|
43
|
+
for n := 1; n <= testSize; n++ {
|
42
44
|
res := Triangle(n)
|
43
|
-
want :=
|
45
|
+
want := triangleTestCases[:n]
|
44
46
|
if !reflect.DeepEqual(res, want) {
|
45
47
|
t.Fatalf("Triangle(%d) = %s,\nwant:%s\n",
|
46
48
|
n, format(res), format(want))
|
47
49
|
}
|
48
50
|
}
|
49
|
-
t.Log(format(Triangle(
|
51
|
+
t.Log(format(Triangle(testSize)))
|
50
52
|
}
|
51
53
|
|
52
54
|
func format(t [][]int) (s string) {
|
@@ -55,3 +57,21 @@ func format(t [][]int) (s string) {
|
|
55
57
|
}
|
56
58
|
return
|
57
59
|
}
|
60
|
+
|
61
|
+
// BenchmarkPascalsTriangleFixed will generate Pascals Triangles against the
|
62
|
+
// solution using triangles of fixed size 20.
|
63
|
+
func BenchmarkPascalsTriangleFixed(b *testing.B) {
|
64
|
+
for i := 0; i < b.N; i++ {
|
65
|
+
Triangle(testSize) // same length as the test for correctness above
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
// BenchmarkPascalsTriangleIncreasing will generate Pascals Triangles against the
|
70
|
+
// solution using triangles of an increasingly larger size from 1 to 20.
|
71
|
+
func BenchmarkPascalsTriangleIncreasing(b *testing.B) {
|
72
|
+
for i := 0; i < b.N; i++ {
|
73
|
+
for x := 0; x <= testSize; x++ {
|
74
|
+
Triangle(x)
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
@@ -43,9 +43,7 @@ type js struct {
|
|
43
43
|
// readme and have no biological basis and so are not converted here.
|
44
44
|
var tmpl = `package strand
|
45
45
|
|
46
|
-
|
47
|
-
{{if .Commit}}// Commit: {{.Commit}}
|
48
|
-
{{end}}
|
46
|
+
{{.Header}}
|
49
47
|
|
50
48
|
var rnaTests = []struct {
|
51
49
|
input string
|
@@ -1,7 +1,8 @@
|
|
1
1
|
package strand
|
2
2
|
|
3
3
|
// Source: exercism/x-common
|
4
|
-
// Commit:
|
4
|
+
// Commit: 0b20fff rna-transcription: Fix canonical-data.json formatting
|
5
|
+
// x-common version: 1.0.0
|
5
6
|
|
6
7
|
var rnaTests = []struct {
|
7
8
|
input string
|
@@ -31,9 +31,7 @@ type js struct {
|
|
31
31
|
// template applied to above data structure generates the Go test cases
|
32
32
|
var tmpl = `package romannumerals
|
33
33
|
|
34
|
-
|
35
|
-
{{if .Commit}}// Commit: {{.Commit}}
|
36
|
-
{{end}}
|
34
|
+
{{.Header}}
|
37
35
|
|
38
36
|
type romanNumeralTest struct {
|
39
37
|
arabic int
|
@@ -1,7 +1,8 @@
|
|
1
1
|
package romannumerals
|
2
2
|
|
3
3
|
// Source: exercism/x-common
|
4
|
-
// Commit:
|
4
|
+
// Commit: 070e8d5 roman-numerals: Fix canonical-data.json formatting
|
5
|
+
// x-common version: 1.0.0
|
5
6
|
|
6
7
|
type romanNumeralTest struct {
|
7
8
|
arabic int
|
@@ -16,7 +16,7 @@ func ToRomanNumeral(input int) (string, error) {
|
|
16
16
|
buffer := bytes.NewBufferString("")
|
17
17
|
|
18
18
|
if input <= 0 || input >= 4000 {
|
19
|
-
return "", fmt.Errorf("
|
19
|
+
return "", fmt.Errorf("the number %d is undefined in the roman numeral system", input)
|
20
20
|
}
|
21
21
|
|
22
22
|
mappings := []arabicToRoman{
|
@@ -32,9 +32,7 @@ type js struct {
|
|
32
32
|
// template applied to above data structure generates the Go test cases
|
33
33
|
var tmpl = `package transpose
|
34
34
|
|
35
|
-
|
36
|
-
{{if .Commit}}// Commit: {{.Commit}}
|
37
|
-
{{end}}
|
35
|
+
{{.Header}}
|
38
36
|
|
39
37
|
var testCases = []struct {
|
40
38
|
description string
|
@@ -17,6 +17,11 @@ func TestTranspose(t *testing.T) {
|
|
17
17
|
for _, test := range testCases {
|
18
18
|
actual := Transpose(test.input)
|
19
19
|
if !reflect.DeepEqual(actual, test.expected) {
|
20
|
+
// check for zero length slices
|
21
|
+
if len(actual) == 0 || len(test.expected) == 0 {
|
22
|
+
t.Fatalf("\n\tTranspose(%q): %s\n\n\tExpected: %q\n\tGot: %q",
|
23
|
+
test.input, test.description, test.expected, actual)
|
24
|
+
}
|
20
25
|
// let's make the error more specific and find the row it's on
|
21
26
|
min := min(len(test.expected), len(actual))
|
22
27
|
for i := 0; i < min; i++ {
|
@@ -32,9 +32,7 @@ type js struct {
|
|
32
32
|
// template applied to above data structure generates the Go test cases
|
33
33
|
var tmpl = `package wordcount
|
34
34
|
|
35
|
-
|
36
|
-
{{if .Commit}}// Commit: {{.Commit}}
|
37
|
-
{{end}}
|
35
|
+
{{.Header}}
|
38
36
|
|
39
37
|
var testCases = []struct {
|
40
38
|
description string
|
@@ -1,7 +1,8 @@
|
|
1
1
|
package wordcount
|
2
2
|
|
3
3
|
// Source: exercism/x-common
|
4
|
-
// Commit:
|
4
|
+
// Commit: cd26d49 word-count: Make exercise schema-compliant (#634)
|
5
|
+
// x-common version: 1.0.0
|
5
6
|
|
6
7
|
var testCases = []struct {
|
7
8
|
description string
|
data/tracks/go/gen/gen.go
CHANGED
@@ -89,10 +89,11 @@ func Gen(exercise string, j interface{}, t *template.Template) error {
|
|
89
89
|
// try to find and read the local json source file
|
90
90
|
log.Printf("[LOCAL] fetching %s test data\n", exercise)
|
91
91
|
jPath, jOrigin, jCommit := getLocal(jFile)
|
92
|
+
jFilePath := filepath.Join(jPath, jFile)
|
92
93
|
if jPath != "" {
|
93
|
-
log.Printf("[LOCAL] source: %s\n",
|
94
|
+
log.Printf("[LOCAL] source: %s\n", jFilePath)
|
94
95
|
}
|
95
|
-
jSrc, err := ioutil.ReadFile(
|
96
|
+
jSrc, err := ioutil.ReadFile(jFilePath)
|
96
97
|
if err != nil {
|
97
98
|
// fetch json data remotely if there's no local file
|
98
99
|
log.Println("[LOCAL] No test data found")
|
data/tracks/java/config.json
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
apply plugin: "java"
|
2
|
+
apply plugin: "eclipse"
|
3
|
+
apply plugin: "idea"
|
4
|
+
|
5
|
+
repositories {
|
6
|
+
mavenCentral()
|
7
|
+
}
|
8
|
+
|
9
|
+
dependencies {
|
10
|
+
testCompile "junit:junit:4.12"
|
11
|
+
}
|
12
|
+
test {
|
13
|
+
testLogging {
|
14
|
+
exceptionFormat = 'full'
|
15
|
+
events = ["passed", "failed", "skipped"]
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import java.util.ArrayList;
|
2
|
+
import java.util.Collections;
|
3
|
+
import java.util.List;
|
4
|
+
|
5
|
+
final class Matrix {
|
6
|
+
|
7
|
+
private final List<List<Integer>> values;
|
8
|
+
|
9
|
+
Matrix(final List<List<Integer>> values) {
|
10
|
+
this.values = values;
|
11
|
+
}
|
12
|
+
|
13
|
+
List<MatrixCoordinate> getSaddlePoints() {
|
14
|
+
final List<MatrixCoordinate> result = new ArrayList<>();
|
15
|
+
|
16
|
+
if (values.isEmpty()) {
|
17
|
+
return result;
|
18
|
+
}
|
19
|
+
|
20
|
+
for (int row = 0; row < values.size(); row++) {
|
21
|
+
for (int column = 0; column < values.get(0).size(); column++) {
|
22
|
+
final int coordinateValue = values.get(row).get(column);
|
23
|
+
|
24
|
+
if (coordinateValue == getRowMax(row) && coordinateValue == getColumnMin(column)) {
|
25
|
+
result.add(new MatrixCoordinate(row, column));
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
return result;
|
31
|
+
}
|
32
|
+
|
33
|
+
private int getRowMax(final int row) {
|
34
|
+
return Collections.max(values.get(row));
|
35
|
+
}
|
36
|
+
|
37
|
+
private int getColumnMin(final int column) {
|
38
|
+
return values.stream()
|
39
|
+
.map(row -> row.get(column))
|
40
|
+
.min(Integer::compareTo)
|
41
|
+
.get();
|
42
|
+
}
|
43
|
+
|
44
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
final class MatrixCoordinate {
|
2
|
+
|
3
|
+
private final int row;
|
4
|
+
|
5
|
+
private final int column;
|
6
|
+
|
7
|
+
MatrixCoordinate(final int row, final int column) {
|
8
|
+
this.row = row;
|
9
|
+
this.column = column;
|
10
|
+
}
|
11
|
+
|
12
|
+
// Generated equals and hashcode.
|
13
|
+
|
14
|
+
@Override
|
15
|
+
public boolean equals(final Object o) {
|
16
|
+
if (this == o) return true;
|
17
|
+
if (o == null || getClass() != o.getClass()) return false;
|
18
|
+
|
19
|
+
final MatrixCoordinate that = (MatrixCoordinate) o;
|
20
|
+
|
21
|
+
return row == that.row && column == that.column;
|
22
|
+
}
|
23
|
+
|
24
|
+
@Override
|
25
|
+
public int hashCode() {
|
26
|
+
int result = row;
|
27
|
+
result = 31 * result + column;
|
28
|
+
return result;
|
29
|
+
}
|
30
|
+
|
31
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
final class MatrixCoordinate {
|
2
|
+
|
3
|
+
private final int row;
|
4
|
+
|
5
|
+
private final int column;
|
6
|
+
|
7
|
+
MatrixCoordinate(final int row, final int column) {
|
8
|
+
this.row = row;
|
9
|
+
this.column = column;
|
10
|
+
}
|
11
|
+
|
12
|
+
// Generated equals and hashcode.
|
13
|
+
|
14
|
+
@Override
|
15
|
+
public boolean equals(final Object o) {
|
16
|
+
if (this == o) return true;
|
17
|
+
if (o == null || getClass() != o.getClass()) return false;
|
18
|
+
|
19
|
+
final MatrixCoordinate that = (MatrixCoordinate) o;
|
20
|
+
|
21
|
+
return row == that.row && column == that.column;
|
22
|
+
}
|
23
|
+
|
24
|
+
@Override
|
25
|
+
public int hashCode() {
|
26
|
+
int result = row;
|
27
|
+
result = 31 * result + column;
|
28
|
+
return result;
|
29
|
+
}
|
30
|
+
|
31
|
+
}
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import org.junit.Ignore;
|
2
|
+
import org.junit.Test;
|
3
|
+
|
4
|
+
import java.util.ArrayList;
|
5
|
+
import java.util.Arrays;
|
6
|
+
import java.util.Collections;
|
7
|
+
import java.util.List;
|
8
|
+
|
9
|
+
import static org.junit.Assert.assertEquals;
|
10
|
+
|
11
|
+
public class MatrixTest {
|
12
|
+
|
13
|
+
@Test
|
14
|
+
public void testCanIdentifySingleSaddlePoint() {
|
15
|
+
Matrix matrix = new Matrix(Arrays.asList(
|
16
|
+
Arrays.asList(9, 8, 7),
|
17
|
+
Arrays.asList(5, 3, 2),
|
18
|
+
Arrays.asList(6, 6, 7)
|
19
|
+
));
|
20
|
+
|
21
|
+
List<MatrixCoordinate> expectedSaddlePoints = Collections.singletonList(new MatrixCoordinate(1, 0));
|
22
|
+
|
23
|
+
assertEquals(expectedSaddlePoints, matrix.getSaddlePoints());
|
24
|
+
}
|
25
|
+
|
26
|
+
@Ignore
|
27
|
+
@Test
|
28
|
+
public void testCanIdentifyThatEmptyMatrixHasNoSaddlePoints() {
|
29
|
+
Matrix matrix = new Matrix(new ArrayList<>());
|
30
|
+
|
31
|
+
List<MatrixCoordinate> expectedSaddlePoints = new ArrayList<>();
|
32
|
+
|
33
|
+
assertEquals(expectedSaddlePoints, matrix.getSaddlePoints());
|
34
|
+
}
|
35
|
+
|
36
|
+
@Ignore
|
37
|
+
@Test
|
38
|
+
public void testCanIdentifyLackOfSaddlePointsWhenThereAreNone() {
|
39
|
+
Matrix matrix = new Matrix(Arrays.asList(
|
40
|
+
Arrays.asList(1, 2, 3),
|
41
|
+
Arrays.asList(3, 1, 2),
|
42
|
+
Arrays.asList(2, 3, 1)
|
43
|
+
));
|
44
|
+
|
45
|
+
List<MatrixCoordinate> expectedSaddlePoints = new ArrayList<>();
|
46
|
+
|
47
|
+
assertEquals(expectedSaddlePoints, matrix.getSaddlePoints());
|
48
|
+
}
|
49
|
+
|
50
|
+
@Ignore
|
51
|
+
@Test
|
52
|
+
public void testCanIdentifyMultipleSaddlePoints() {
|
53
|
+
Matrix matrix = new Matrix(Arrays.asList(
|
54
|
+
Arrays.asList(4, 5, 4),
|
55
|
+
Arrays.asList(3, 5, 5),
|
56
|
+
Arrays.asList(1, 5, 4)
|
57
|
+
));
|
58
|
+
|
59
|
+
List<MatrixCoordinate> expectedSaddlePoints = Arrays.asList(
|
60
|
+
new MatrixCoordinate(0, 1),
|
61
|
+
new MatrixCoordinate(1, 1),
|
62
|
+
new MatrixCoordinate(2, 1)
|
63
|
+
);
|
64
|
+
|
65
|
+
assertEquals(expectedSaddlePoints, matrix.getSaddlePoints());
|
66
|
+
}
|
67
|
+
|
68
|
+
@Ignore
|
69
|
+
@Test
|
70
|
+
public void testCanIdentifySaddlePointInBottomRightCorner() {
|
71
|
+
Matrix matrix = new Matrix(Arrays.asList(
|
72
|
+
Arrays.asList(8, 7, 9),
|
73
|
+
Arrays.asList(6, 7, 6),
|
74
|
+
Arrays.asList(3, 2, 5)
|
75
|
+
));
|
76
|
+
|
77
|
+
List<MatrixCoordinate> expectedSaddlePoints = Collections.singletonList(new MatrixCoordinate(2, 2));
|
78
|
+
|
79
|
+
assertEquals(expectedSaddlePoints, matrix.getSaddlePoints());
|
80
|
+
}
|
81
|
+
|
82
|
+
}
|