trackler 2.1.0.28 → 2.1.0.29
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/ceylon/README.md +1 -1
- data/tracks/java/config.json +5 -0
- data/tracks/java/exercises/settings.gradle +1 -0
- data/tracks/java/exercises/word-search/build.gradle +18 -0
- data/tracks/java/exercises/word-search/src/example/java/Pair.java +37 -0
- data/tracks/java/exercises/word-search/src/example/java/WordLocation.java +29 -0
- data/tracks/java/exercises/word-search/src/example/java/WordSearcher.java +94 -0
- data/tracks/java/exercises/word-search/src/main/java/Pair.java +37 -0
- data/tracks/java/exercises/word-search/src/main/java/WordLocation.java +29 -0
- data/tracks/java/exercises/word-search/src/test/java/WordSearcherTest.java +278 -0
- data/tracks/scala/README.md +4 -7
- data/tracks/scala/config.json +11 -10
- data/tracks/scala/exercises/beer-song/src/test/scala/BeerSongTest.scala +2 -1
- data/tracks/scala/exercises/perfect-numbers/example.scala +14 -10
- data/tracks/scala/exercises/perfect-numbers/src/test/scala/PerfectNumbersTest.scala +34 -27
- data/tracks/scala/testgen/src/main/scala/BeerSongTestGenerator.scala +2 -0
- data/tracks/scala/testgen/src/main/scala/PerfectNumbersTestGenerator.scala +42 -0
- data/tracks/scala/testgen/src/main/scala/testgen/CanonicalDataParser.scala +1 -1
- data/tracks/scala/testgen/src/main/scala/testgen/TestSuiteBuilder.scala +2 -2
- data/tracks/vimscript/config.json +6 -2
- data/tracks/vimscript/exercises/etl/etl.vader +27 -0
- data/tracks/vimscript/exercises/etl/etl.vim +12 -0
- data/tracks/vimscript/exercises/etl/example.vim +11 -0
- metadata +13 -3
- data/tracks/scala/exercises/perfect-numbers/src/main/scala/PerfectNumbers.scala +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73dfe16b1709780cb1c87bc8a36da3a089c2ea4e
|
4
|
+
data.tar.gz: 41508819e3d7596fc565fad1029ca178ada8d123
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c2a66c4a2a066f2a5fa9655a3ec3c9ee78d0ef560f9fa6b3ae7e0d1369f4c40a02cdb61c757079709cc87ec1fb0039b0cc1e50452b482e26c8869aeafc96121
|
7
|
+
data.tar.gz: 2c1dd36f3e6189b96fc37dac36f2bb23e3802f74abe75383547f5f5962ed18d20269a5a05dc4ec163ab077ef128562aa59893e1ec49d5aa89e4420920cd4ffd5
|
data/lib/trackler/version.rb
CHANGED
data/tracks/ceylon/README.md
CHANGED
@@ -13,7 +13,7 @@ You can just ask in the [Exercism Gitter support](https://gitter.im/exercism/sup
|
|
13
13
|
|
14
14
|
### How to contribute
|
15
15
|
|
16
|
-
The Exercism-wide [contributing guide](https://github.com/exercism/
|
16
|
+
The Exercism-wide [contributing guide](https://github.com/exercism/docs/tree/master/contributing-to-language-tracks) covers topics relevant to contributing to the entire Exercism project, including but not limited to the Ceylon track.
|
17
17
|
|
18
18
|
* To report a bug or ask a question, [create an issue](https://help.github.com/articles/creating-an-issue/).
|
19
19
|
* If you already have a fix for a bug, you could [create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
|
data/tracks/java/config.json
CHANGED
@@ -0,0 +1,18 @@
|
|
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
|
+
|
13
|
+
test {
|
14
|
+
testLogging {
|
15
|
+
exceptionFormat = 'full'
|
16
|
+
events = ["passed", "failed", "skipped"]
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Pair {
|
2
|
+
|
3
|
+
private final int x;
|
4
|
+
|
5
|
+
private final int y;
|
6
|
+
|
7
|
+
Pair(final int x, final int y) {
|
8
|
+
this.y = y;
|
9
|
+
this.x = x;
|
10
|
+
}
|
11
|
+
|
12
|
+
int getX() {
|
13
|
+
return x;
|
14
|
+
}
|
15
|
+
|
16
|
+
int getY() {
|
17
|
+
return y;
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
public boolean equals(final Object o) {
|
22
|
+
if (this == o) return true;
|
23
|
+
if (o == null || getClass() != o.getClass()) return false;
|
24
|
+
|
25
|
+
Pair pair = (Pair) o;
|
26
|
+
|
27
|
+
return x == pair.x && y == pair.y;
|
28
|
+
}
|
29
|
+
|
30
|
+
@Override
|
31
|
+
public int hashCode() {
|
32
|
+
int result = x;
|
33
|
+
result = 31 * result + y;
|
34
|
+
return result;
|
35
|
+
}
|
36
|
+
|
37
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class WordLocation {
|
2
|
+
|
3
|
+
private final Pair startCoord;
|
4
|
+
|
5
|
+
private final Pair endCoord;
|
6
|
+
|
7
|
+
WordLocation(final Pair startCoord, final Pair endCoord) {
|
8
|
+
this.startCoord = startCoord;
|
9
|
+
this.endCoord = endCoord;
|
10
|
+
}
|
11
|
+
|
12
|
+
@Override
|
13
|
+
public boolean equals(final Object o) {
|
14
|
+
if (this == o) return true;
|
15
|
+
if (o == null || getClass() != o.getClass()) return false;
|
16
|
+
|
17
|
+
WordLocation that = (WordLocation) o;
|
18
|
+
|
19
|
+
return startCoord.equals(that.startCoord) && endCoord.equals(that.endCoord);
|
20
|
+
}
|
21
|
+
|
22
|
+
@Override
|
23
|
+
public int hashCode() {
|
24
|
+
int result = startCoord.hashCode();
|
25
|
+
result = 31 * result + endCoord.hashCode();
|
26
|
+
return result;
|
27
|
+
}
|
28
|
+
|
29
|
+
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
import java.util.*;
|
2
|
+
import java.util.function.Function;
|
3
|
+
import java.util.stream.Collectors;
|
4
|
+
|
5
|
+
class WordSearcher {
|
6
|
+
|
7
|
+
private static final List<Pair> DIRECTIONS = Arrays.asList(
|
8
|
+
new Pair( 1, 0), // N
|
9
|
+
new Pair( 1, 1), // NE
|
10
|
+
new Pair( 0, 1), // E
|
11
|
+
new Pair(-1, 1), // SE
|
12
|
+
new Pair(-1, 0), // S
|
13
|
+
new Pair(-1, -1), // SW
|
14
|
+
new Pair( 0, -1), // W
|
15
|
+
new Pair( 1, -1)); // NW
|
16
|
+
|
17
|
+
/*
|
18
|
+
* Search for multiple words in the given grid.
|
19
|
+
*/
|
20
|
+
Map<String, Optional<WordLocation>> search(final Set<String> words, final char[][] grid) {
|
21
|
+
return words
|
22
|
+
.stream()
|
23
|
+
.collect(Collectors.toMap(Function.identity(), s -> search(s, grid)));
|
24
|
+
}
|
25
|
+
|
26
|
+
/*
|
27
|
+
* Search for a single word in the given grid.
|
28
|
+
*/
|
29
|
+
private Optional<WordLocation> search(final CharSequence word, final char[][] grid) {
|
30
|
+
final int nRows = grid.length;
|
31
|
+
final int nCols = grid[0].length;
|
32
|
+
|
33
|
+
// 1-indexed
|
34
|
+
for (int c = 1; c <= nCols; c++) {
|
35
|
+
for (int r = 1; r <= nRows; r++) {
|
36
|
+
final Optional<WordLocation> wordLocation = search(word, grid, new Pair(c, r));
|
37
|
+
if (wordLocation.isPresent()) return wordLocation;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
return Optional.empty();
|
42
|
+
}
|
43
|
+
|
44
|
+
/*
|
45
|
+
* Search for a single word starting at a given coordinate within the given grid.
|
46
|
+
*/
|
47
|
+
private Optional<WordLocation> search(final CharSequence word, final char[][] grid, final Pair startCoord) {
|
48
|
+
if (grid[startCoord.getY() - 1][startCoord.getX() - 1] != word.charAt(0)) return Optional.empty();
|
49
|
+
|
50
|
+
for (final Pair direction : DIRECTIONS) {
|
51
|
+
final Optional<WordLocation> wordLocation = check(word, grid, startCoord, direction);
|
52
|
+
if (wordLocation.isPresent()) return wordLocation;
|
53
|
+
}
|
54
|
+
|
55
|
+
return Optional.empty();
|
56
|
+
}
|
57
|
+
|
58
|
+
/*
|
59
|
+
* Check whether a single word starts at a given coordinate and is aligned in a given direction within the given
|
60
|
+
* grid.
|
61
|
+
*/
|
62
|
+
private Optional<WordLocation> check(
|
63
|
+
final CharSequence word,
|
64
|
+
final char[][] grid,
|
65
|
+
final Pair startCoord,
|
66
|
+
final Pair direction) {
|
67
|
+
|
68
|
+
final int nRows = grid.length;
|
69
|
+
final int nCols = grid[0].length;
|
70
|
+
|
71
|
+
Pair nextCoord = startCoord;
|
72
|
+
|
73
|
+
for (int charIndex = 1; charIndex < word.length(); charIndex++) {
|
74
|
+
nextCoord = new Pair(
|
75
|
+
startCoord.getX() + charIndex * direction.getX(),
|
76
|
+
startCoord.getY() + charIndex * direction.getY());
|
77
|
+
|
78
|
+
if (nextCoord.getY() < 1 ||
|
79
|
+
nextCoord.getY() > nRows ||
|
80
|
+
nextCoord.getX() < 1 ||
|
81
|
+
nextCoord.getX() > nCols) {
|
82
|
+
|
83
|
+
return Optional.empty();
|
84
|
+
}
|
85
|
+
|
86
|
+
if (grid[nextCoord.getY() - 1][nextCoord.getX() - 1] != word.charAt(charIndex)) {
|
87
|
+
return Optional.empty();
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
return Optional.of(new WordLocation(startCoord, nextCoord));
|
92
|
+
}
|
93
|
+
|
94
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Pair {
|
2
|
+
|
3
|
+
private final int x;
|
4
|
+
|
5
|
+
private final int y;
|
6
|
+
|
7
|
+
Pair(final int x, final int y) {
|
8
|
+
this.y = y;
|
9
|
+
this.x = x;
|
10
|
+
}
|
11
|
+
|
12
|
+
int getX() {
|
13
|
+
return x;
|
14
|
+
}
|
15
|
+
|
16
|
+
int getY() {
|
17
|
+
return y;
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
public boolean equals(final Object o) {
|
22
|
+
if (this == o) return true;
|
23
|
+
if (o == null || getClass() != o.getClass()) return false;
|
24
|
+
|
25
|
+
Pair pair = (Pair) o;
|
26
|
+
|
27
|
+
return x == pair.x && y == pair.y;
|
28
|
+
}
|
29
|
+
|
30
|
+
@Override
|
31
|
+
public int hashCode() {
|
32
|
+
int result = x;
|
33
|
+
result = 31 * result + y;
|
34
|
+
return result;
|
35
|
+
}
|
36
|
+
|
37
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class WordLocation {
|
2
|
+
|
3
|
+
private final Pair startCoord;
|
4
|
+
|
5
|
+
private final Pair endCoord;
|
6
|
+
|
7
|
+
WordLocation(final Pair startCoord, final Pair endCoord) {
|
8
|
+
this.startCoord = startCoord;
|
9
|
+
this.endCoord = endCoord;
|
10
|
+
}
|
11
|
+
|
12
|
+
@Override
|
13
|
+
public boolean equals(final Object o) {
|
14
|
+
if (this == o) return true;
|
15
|
+
if (o == null || getClass() != o.getClass()) return false;
|
16
|
+
|
17
|
+
WordLocation that = (WordLocation) o;
|
18
|
+
|
19
|
+
return startCoord.equals(that.startCoord) && endCoord.equals(that.endCoord);
|
20
|
+
}
|
21
|
+
|
22
|
+
@Override
|
23
|
+
public int hashCode() {
|
24
|
+
int result = startCoord.hashCode();
|
25
|
+
result = 31 * result + endCoord.hashCode();
|
26
|
+
return result;
|
27
|
+
}
|
28
|
+
|
29
|
+
}
|
@@ -0,0 +1,278 @@
|
|
1
|
+
import org.junit.Before;
|
2
|
+
import org.junit.Test;
|
3
|
+
|
4
|
+
import java.util.*;
|
5
|
+
|
6
|
+
import static org.junit.Assert.assertEquals;
|
7
|
+
|
8
|
+
/*
|
9
|
+
* version: 1.0.0
|
10
|
+
*/
|
11
|
+
public class WordSearcherTest {
|
12
|
+
|
13
|
+
private WordSearcher wordSearcher;
|
14
|
+
|
15
|
+
@Before
|
16
|
+
public void setUp() {
|
17
|
+
wordSearcher = new WordSearcher();
|
18
|
+
}
|
19
|
+
|
20
|
+
@Test
|
21
|
+
public void testLocatesWordsWrittenLeftToRight() {
|
22
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
23
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair(1, 10), new Pair(7, 10))));
|
24
|
+
|
25
|
+
Set<String> searchWords = expectedLocations.keySet();
|
26
|
+
|
27
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
28
|
+
searchWords,
|
29
|
+
new char[][]{
|
30
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
31
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
32
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
33
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
34
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
35
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
36
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
37
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
38
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
39
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}
|
40
|
+
}
|
41
|
+
);
|
42
|
+
|
43
|
+
assertEquals(expectedLocations, actualLocations);
|
44
|
+
}
|
45
|
+
|
46
|
+
@Test
|
47
|
+
public void testLocatesWordsWrittenRightToLeft() {
|
48
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
49
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair(1, 10), new Pair(7, 10))));
|
50
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair(6, 5), new Pair(1, 5))));
|
51
|
+
|
52
|
+
Set<String> searchWords = expectedLocations.keySet();
|
53
|
+
|
54
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
55
|
+
searchWords,
|
56
|
+
new char[][]{
|
57
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
58
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
59
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
60
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
61
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
62
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
63
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
64
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
65
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
66
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}
|
67
|
+
}
|
68
|
+
);
|
69
|
+
|
70
|
+
assertEquals(expectedLocations, actualLocations);
|
71
|
+
}
|
72
|
+
|
73
|
+
@Test
|
74
|
+
public void testLocatesWordsWrittenTopToBottom() {
|
75
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
76
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair( 1, 10), new Pair( 7, 10))));
|
77
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair( 6, 5), new Pair( 1, 5))));
|
78
|
+
expectedLocations.put("ecmascript", Optional.of(new WordLocation(new Pair(10, 1), new Pair(10, 10))));
|
79
|
+
|
80
|
+
Set<String> searchWords = expectedLocations.keySet();
|
81
|
+
|
82
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
83
|
+
searchWords,
|
84
|
+
new char[][]{
|
85
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
86
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
87
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
88
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
89
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
90
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
91
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
92
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
93
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
94
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}
|
95
|
+
}
|
96
|
+
);
|
97
|
+
|
98
|
+
assertEquals(expectedLocations, actualLocations);
|
99
|
+
}
|
100
|
+
|
101
|
+
@Test
|
102
|
+
public void testLocatesWordsWrittenBottomToTop() {
|
103
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
104
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair( 1, 10), new Pair( 7, 10))));
|
105
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair( 6, 5), new Pair( 1, 5))));
|
106
|
+
expectedLocations.put("ecmascript", Optional.of(new WordLocation(new Pair(10, 1), new Pair(10, 10))));
|
107
|
+
expectedLocations.put("rust", Optional.of(new WordLocation(new Pair( 9, 5), new Pair( 9, 2))));
|
108
|
+
|
109
|
+
Set<String> searchWords = expectedLocations.keySet();
|
110
|
+
|
111
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
112
|
+
searchWords,
|
113
|
+
new char[][]{
|
114
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
115
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
116
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
117
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
118
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
119
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
120
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
121
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
122
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
123
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}});
|
124
|
+
|
125
|
+
assertEquals(expectedLocations, actualLocations);
|
126
|
+
}
|
127
|
+
|
128
|
+
@Test
|
129
|
+
public void testLocatesWordsWrittenTopLeftToBottomRight() {
|
130
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
131
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair( 1, 10), new Pair( 7, 10))));
|
132
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair( 6, 5), new Pair( 1, 5))));
|
133
|
+
expectedLocations.put("ecmascript", Optional.of(new WordLocation(new Pair(10, 1), new Pair(10, 10))));
|
134
|
+
expectedLocations.put("rust", Optional.of(new WordLocation(new Pair( 9, 5), new Pair( 9, 2))));
|
135
|
+
expectedLocations.put("java", Optional.of(new WordLocation(new Pair( 1, 1), new Pair( 4, 4))));
|
136
|
+
|
137
|
+
Set<String> searchWords = expectedLocations.keySet();
|
138
|
+
|
139
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
140
|
+
searchWords,
|
141
|
+
new char[][]{
|
142
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
143
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
144
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
145
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
146
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
147
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
148
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
149
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
150
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
151
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}});
|
152
|
+
|
153
|
+
assertEquals(expectedLocations, actualLocations);
|
154
|
+
}
|
155
|
+
|
156
|
+
@Test
|
157
|
+
public void testLocatesWordsWrittenBottomRightToTopLeft() {
|
158
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
159
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair( 1, 10), new Pair( 7, 10))));
|
160
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair( 6, 5), new Pair( 1, 5))));
|
161
|
+
expectedLocations.put("ecmascript", Optional.of(new WordLocation(new Pair(10, 1), new Pair(10, 10))));
|
162
|
+
expectedLocations.put("rust", Optional.of(new WordLocation(new Pair( 9, 5), new Pair( 9, 2))));
|
163
|
+
expectedLocations.put("java", Optional.of(new WordLocation(new Pair( 1, 1), new Pair( 4, 4))));
|
164
|
+
expectedLocations.put("lua", Optional.of(new WordLocation(new Pair( 8, 9), new Pair( 6, 7))));
|
165
|
+
|
166
|
+
Set<String> searchWords = expectedLocations.keySet();
|
167
|
+
|
168
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
169
|
+
searchWords,
|
170
|
+
new char[][]{
|
171
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
172
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
173
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
174
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
175
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
176
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
177
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
178
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
179
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
180
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}});
|
181
|
+
|
182
|
+
assertEquals(expectedLocations, actualLocations);
|
183
|
+
}
|
184
|
+
|
185
|
+
@Test
|
186
|
+
public void testLocatesWordsWrittenBottomLeftToTopRight() {
|
187
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
188
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair( 1, 10), new Pair( 7, 10))));
|
189
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair( 6, 5), new Pair( 1, 5))));
|
190
|
+
expectedLocations.put("ecmascript", Optional.of(new WordLocation(new Pair(10, 1), new Pair(10, 10))));
|
191
|
+
expectedLocations.put("rust", Optional.of(new WordLocation(new Pair( 9, 5), new Pair( 9, 2))));
|
192
|
+
expectedLocations.put("java", Optional.of(new WordLocation(new Pair( 1, 1), new Pair( 4, 4))));
|
193
|
+
expectedLocations.put("lua", Optional.of(new WordLocation(new Pair( 8, 9), new Pair( 6, 7))));
|
194
|
+
expectedLocations.put("lisp", Optional.of(new WordLocation(new Pair( 3, 6), new Pair( 6, 3))));
|
195
|
+
|
196
|
+
Set<String> searchWords = expectedLocations.keySet();
|
197
|
+
|
198
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
199
|
+
searchWords,
|
200
|
+
new char[][]{
|
201
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
202
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
203
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
204
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
205
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
206
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
207
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
208
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
209
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
210
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}});
|
211
|
+
|
212
|
+
assertEquals(expectedLocations, actualLocations);
|
213
|
+
}
|
214
|
+
|
215
|
+
@Test
|
216
|
+
public void testLocatesWordsWrittenTopRightToBottomLeft() {
|
217
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
218
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair( 1, 10), new Pair( 7, 10))));
|
219
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair( 6, 5), new Pair( 1, 5))));
|
220
|
+
expectedLocations.put("ecmascript", Optional.of(new WordLocation(new Pair(10, 1), new Pair(10, 10))));
|
221
|
+
expectedLocations.put("rust", Optional.of(new WordLocation(new Pair( 9, 5), new Pair( 9, 2))));
|
222
|
+
expectedLocations.put("java", Optional.of(new WordLocation(new Pair( 1, 1), new Pair( 4, 4))));
|
223
|
+
expectedLocations.put("lua", Optional.of(new WordLocation(new Pair( 8, 9), new Pair( 6, 7))));
|
224
|
+
expectedLocations.put("lisp", Optional.of(new WordLocation(new Pair( 3, 6), new Pair( 6, 3))));
|
225
|
+
expectedLocations.put("ruby", Optional.of(new WordLocation(new Pair( 8, 6), new Pair( 5, 9))));
|
226
|
+
|
227
|
+
Set<String> searchWords = expectedLocations.keySet();
|
228
|
+
|
229
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
230
|
+
searchWords,
|
231
|
+
new char[][]{
|
232
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
233
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
234
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
235
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
236
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
237
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
238
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
239
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
240
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
241
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}});
|
242
|
+
|
243
|
+
assertEquals(expectedLocations, actualLocations);
|
244
|
+
}
|
245
|
+
|
246
|
+
@Test
|
247
|
+
public void testFailsToLocateAWordsThatIsNotInThePuzzle() {
|
248
|
+
Map<String, Optional<WordLocation>> expectedLocations = new HashMap<>();
|
249
|
+
expectedLocations.put("clojure", Optional.of(new WordLocation(new Pair( 1, 10), new Pair( 7, 10))));
|
250
|
+
expectedLocations.put("elixir", Optional.of(new WordLocation(new Pair( 6, 5), new Pair( 1, 5))));
|
251
|
+
expectedLocations.put("ecmascript", Optional.of(new WordLocation(new Pair(10, 1), new Pair(10, 10))));
|
252
|
+
expectedLocations.put("rust", Optional.of(new WordLocation(new Pair( 9, 5), new Pair( 9, 2))));
|
253
|
+
expectedLocations.put("java", Optional.of(new WordLocation(new Pair( 1, 1), new Pair( 4, 4))));
|
254
|
+
expectedLocations.put("lua", Optional.of(new WordLocation(new Pair( 8, 9), new Pair( 6, 7))));
|
255
|
+
expectedLocations.put("lisp", Optional.of(new WordLocation(new Pair( 3, 6), new Pair( 6, 3))));
|
256
|
+
expectedLocations.put("ruby", Optional.of(new WordLocation(new Pair( 8, 6), new Pair( 5, 9))));
|
257
|
+
expectedLocations.put("haskell", Optional.empty());
|
258
|
+
|
259
|
+
Set<String> searchWords = expectedLocations.keySet();
|
260
|
+
|
261
|
+
Map<String, Optional<WordLocation>> actualLocations = wordSearcher.search(
|
262
|
+
searchWords,
|
263
|
+
new char[][]{
|
264
|
+
{'j', 'e', 'f', 'b', 'l', 'p', 'e', 'p', 'r', 'e'},
|
265
|
+
{'c', 'a', 'm', 'd', 'c', 'i', 'm', 'g', 't', 'c'},
|
266
|
+
{'o', 'i', 'v', 'o', 'k', 'p', 'r', 'j', 's', 'm'},
|
267
|
+
{'p', 'b', 'w', 'a', 's', 'q', 'r', 'o', 'u', 'a'},
|
268
|
+
{'r', 'i', 'x', 'i', 'l', 'e', 'l', 'h', 'r', 's'},
|
269
|
+
{'w', 'o', 'l', 'c', 'q', 'l', 'i', 'r', 'p', 'c'},
|
270
|
+
{'s', 'c', 'r', 'e', 'e', 'a', 'u', 'm', 'g', 'r'},
|
271
|
+
{'a', 'l', 'x', 'h', 'p', 'b', 'u', 'r', 'y', 'i'},
|
272
|
+
{'j', 'a', 'l', 'a', 'y', 'c', 'a', 'l', 'm', 'p'},
|
273
|
+
{'c', 'l', 'o', 'j', 'u', 'r', 'e', 'r', 'm', 't'}});
|
274
|
+
|
275
|
+
assertEquals(expectedLocations, actualLocations);
|
276
|
+
}
|
277
|
+
|
278
|
+
}
|
data/tracks/scala/README.md
CHANGED
@@ -17,18 +17,15 @@ suite generators are named in the form `ProblemNameTestGenerator.scala`. Where
|
|
17
17
|
|
18
18
|
[the shared problem metadata](https://github.com/exercism/x-common).
|
19
19
|
|
20
|
-
For example, take a look at the `
|
20
|
+
For example, take a look at the `bob/canonical-data.json` file in the x-common repository, as well
|
21
21
|
as the following files in the xscala repository:
|
22
22
|
|
23
|
-
1. `testgen/src/main/scala/
|
24
|
-
1. `exercises/
|
23
|
+
1. `testgen/src/main/scala/BobTestGenerator.scala` - test suite generator for bob
|
24
|
+
1. `exercises/bob/src/test/scala/BobTest.scala`- generated test suite
|
25
25
|
|
26
|
-
Since a generator was used, the`exercises/
|
26
|
+
Since a generator was used, the`exercises/bob/src/test/scala/BobTest.scala` will never be edited directly.
|
27
27
|
If there's a missing test case, then additional inputs/outputs should be submitted to the x-common repository.
|
28
28
|
|
29
|
-
Note that the the test suite generators do not format the test suite source code. The generated test suite should be
|
30
|
-
formatted before being submitted.
|
31
|
-
|
32
29
|
When submitting new exercises we encourage that a test suite generator and generated test suite is
|
33
30
|
included.
|
34
31
|
|
data/tracks/scala/config.json
CHANGED
@@ -95,16 +95,7 @@
|
|
95
95
|
"Logic",
|
96
96
|
"Transforming"
|
97
97
|
]
|
98
|
-
},
|
99
|
-
{
|
100
|
-
"slug":"perfect-numbers",
|
101
|
-
"difficulty":2,
|
102
|
-
"topics":[
|
103
|
-
"Enumerations",
|
104
|
-
"Integers",
|
105
|
-
"Mathematics"
|
106
|
-
]
|
107
|
-
},
|
98
|
+
},
|
108
99
|
{
|
109
100
|
"slug":"hamming",
|
110
101
|
"difficulty":3,
|
@@ -185,6 +176,16 @@
|
|
185
176
|
"Mathematics"
|
186
177
|
]
|
187
178
|
},
|
179
|
+
{
|
180
|
+
"slug":"perfect-numbers",
|
181
|
+
"difficulty":3,
|
182
|
+
"topics":[
|
183
|
+
"Discriminated unions",
|
184
|
+
"Enumerations",
|
185
|
+
"Integers",
|
186
|
+
"Mathematics"
|
187
|
+
]
|
188
|
+
},
|
188
189
|
{
|
189
190
|
"slug":"binary-search",
|
190
191
|
"difficulty":3,
|
@@ -1,17 +1,21 @@
|
|
1
1
|
import NumberType.NumberType
|
2
2
|
|
3
3
|
object PerfectNumbers {
|
4
|
-
def classify(n: Int): NumberType = {
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
def classify(n: Int): Either[String, NumberType] = {
|
5
|
+
if (n <= 0)
|
6
|
+
Left("Classification is only possible for natural numbers.")
|
7
|
+
else {
|
8
|
+
val sumOfFactors
|
9
|
+
= (1 until n)
|
10
|
+
.foldLeft(0)((acc, i) => if (n % i == 0) acc + i else acc)
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
if (sumOfFactors < n)
|
13
|
+
Right(NumberType.Deficient)
|
14
|
+
else if (sumOfFactors > n)
|
15
|
+
Right(NumberType.Abundant)
|
16
|
+
else
|
17
|
+
Right(NumberType.Perfect)
|
18
|
+
}
|
15
19
|
}
|
16
20
|
}
|
17
21
|
|
@@ -1,62 +1,69 @@
|
|
1
|
-
import org.scalatest.{
|
1
|
+
import org.scalatest.{Matchers, FunSuite}
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
/** @version 1.0.1 */
|
4
|
+
class PerfectNumbersTest extends FunSuite with Matchers {
|
5
|
+
|
6
|
+
test("Smallest perfect number is classified correctly") {
|
7
|
+
PerfectNumbers.classify(6) should be (Right(NumberType.Perfect))
|
8
|
+
}
|
9
|
+
|
10
|
+
test("Medium perfect number is classified correctly") {
|
11
|
+
pending
|
12
|
+
PerfectNumbers.classify(28) should be (Right(NumberType.Perfect))
|
6
13
|
}
|
7
14
|
|
8
|
-
|
15
|
+
test("Large perfect number is classified correctly") {
|
9
16
|
pending
|
10
|
-
PerfectNumbers.classify(
|
17
|
+
PerfectNumbers.classify(33550336) should be (Right(NumberType.Perfect))
|
11
18
|
}
|
12
19
|
|
13
|
-
|
20
|
+
test("Smallest abundant number is classified correctly") {
|
14
21
|
pending
|
15
|
-
PerfectNumbers.classify(
|
22
|
+
PerfectNumbers.classify(12) should be (Right(NumberType.Abundant))
|
16
23
|
}
|
17
24
|
|
18
|
-
|
25
|
+
test("Medium abundant number is classified correctly") {
|
19
26
|
pending
|
20
|
-
PerfectNumbers.classify(
|
27
|
+
PerfectNumbers.classify(30) should be (Right(NumberType.Abundant))
|
21
28
|
}
|
22
29
|
|
23
|
-
|
30
|
+
test("Large abundant number is classified correctly") {
|
24
31
|
pending
|
25
|
-
PerfectNumbers.classify(
|
32
|
+
PerfectNumbers.classify(33550335) should be (Right(NumberType.Abundant))
|
26
33
|
}
|
27
34
|
|
28
|
-
|
35
|
+
test("Smallest prime deficient number is classified correctly") {
|
29
36
|
pending
|
30
|
-
PerfectNumbers.classify(
|
37
|
+
PerfectNumbers.classify(2) should be (Right(NumberType.Deficient))
|
31
38
|
}
|
32
39
|
|
33
|
-
|
40
|
+
test("Smallest non-prime deficient number is classified correctly") {
|
34
41
|
pending
|
35
|
-
PerfectNumbers.classify(
|
42
|
+
PerfectNumbers.classify(4) should be (Right(NumberType.Deficient))
|
36
43
|
}
|
37
44
|
|
38
|
-
|
45
|
+
test("Medium deficient number is classified correctly") {
|
39
46
|
pending
|
40
|
-
PerfectNumbers.classify(
|
47
|
+
PerfectNumbers.classify(32) should be (Right(NumberType.Deficient))
|
41
48
|
}
|
42
49
|
|
43
|
-
|
50
|
+
test("Large deficient number is classified correctly") {
|
44
51
|
pending
|
45
|
-
PerfectNumbers.classify(
|
52
|
+
PerfectNumbers.classify(33550337) should be (Right(NumberType.Deficient))
|
46
53
|
}
|
47
54
|
|
48
|
-
|
55
|
+
test("Edge case (no factors other than itself) is classified correctly") {
|
49
56
|
pending
|
50
|
-
PerfectNumbers.classify(
|
57
|
+
PerfectNumbers.classify(1) should be (Right(NumberType.Deficient))
|
51
58
|
}
|
52
59
|
|
53
|
-
|
60
|
+
test("Zero is rejected (not a natural number)") {
|
54
61
|
pending
|
55
|
-
PerfectNumbers.classify(
|
62
|
+
PerfectNumbers.classify(0) should be (Left("Classification is only possible for natural numbers."))
|
56
63
|
}
|
57
64
|
|
58
|
-
|
65
|
+
test("Negative integer is rejected (not a natural number)") {
|
59
66
|
pending
|
60
|
-
PerfectNumbers.classify(
|
67
|
+
PerfectNumbers.classify(-1) should be (Left("Classification is only possible for natural numbers."))
|
61
68
|
}
|
62
|
-
}
|
69
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import java.io.File
|
2
|
+
|
3
|
+
import testgen.TestSuiteBuilder.{toString, _}
|
4
|
+
import testgen._
|
5
|
+
|
6
|
+
object PerfectNumbersTestGenerator {
|
7
|
+
def main(args: Array[String]): Unit = {
|
8
|
+
val file = new File("src/main/resources/perfect-numbers.json")
|
9
|
+
|
10
|
+
def toEnumStr(str: String): String = {
|
11
|
+
str match {
|
12
|
+
case "perfect" => "NumberType.Perfect"
|
13
|
+
case "abundant" => "NumberType.Abundant"
|
14
|
+
case "deficient" => "NumberType.Deficient"
|
15
|
+
case _ => throw new IllegalStateException("Invalid NumberType -" + str)
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
def toString(expected: CanonicalDataParser.Expected): String = {
|
20
|
+
expected match {
|
21
|
+
case Left(error) => s"Left(${TestSuiteBuilder.toString(error)})"
|
22
|
+
case Right(exp) => s"Right(${toEnumStr(exp.toString)})"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
def fromLabeledTest(argNames: String*): ToTestCaseData =
|
27
|
+
withLabeledTest { sut =>
|
28
|
+
labeledTest =>
|
29
|
+
val args = sutArgs(labeledTest.result, argNames: _*)
|
30
|
+
val property = labeledTest.property
|
31
|
+
val sutCall =
|
32
|
+
s"""PerfectNumbers.$property($args)"""
|
33
|
+
val expected = toString(labeledTest.expected)
|
34
|
+
TestCaseData(labeledTest.description, sutCall, expected)
|
35
|
+
}
|
36
|
+
|
37
|
+
val code = TestSuiteBuilder.build(file, fromLabeledTest("input"))
|
38
|
+
println(s"-------------")
|
39
|
+
println(code)
|
40
|
+
println(s"-------------")
|
41
|
+
}
|
42
|
+
}
|
@@ -66,7 +66,7 @@ object Exercise {
|
|
66
66
|
private def flattenCases(cases: Cases): Cases =
|
67
67
|
cases match {
|
68
68
|
case Seq() => Seq()
|
69
|
-
case (ltg: LabeledTestGroup) +: xs => ltg.cases ++ flattenCases(xs)
|
69
|
+
case (ltg: LabeledTestGroup) +: xs => flattenCases(ltg.cases) ++ flattenCases(xs)
|
70
70
|
case (lt: LabeledTest) +: xs => lt +: flattenCases(xs)
|
71
71
|
}
|
72
72
|
}
|
@@ -86,7 +86,7 @@ object TestSuiteBuilder {
|
|
86
86
|
private def toString(expected: CanonicalDataParser.Expected): String =
|
87
87
|
expected.fold(error => s"Left(${toString(error)})", toString)
|
88
88
|
|
89
|
-
|
89
|
+
def toString(any: Any): String = {
|
90
90
|
def quote(str: String): String =
|
91
91
|
if ("\"\n" exists (str.contains(_:Char))) "\"\"\"" else "\""
|
92
92
|
|
@@ -98,7 +98,7 @@ object TestSuiteBuilder {
|
|
98
98
|
}
|
99
99
|
}
|
100
100
|
|
101
|
-
def
|
101
|
+
def writeToFile(text: String, dest: File): Unit = {
|
102
102
|
val fileWriter = new FileWriter(dest)
|
103
103
|
try { fileWriter.write(text) } finally fileWriter.close
|
104
104
|
}
|
@@ -73,8 +73,7 @@
|
|
73
73
|
{
|
74
74
|
"slug": "allergies",
|
75
75
|
"difficulty": 1,
|
76
|
-
"topics": [
|
77
|
-
]
|
76
|
+
"topics": []
|
78
77
|
},
|
79
78
|
{
|
80
79
|
"slug": "scrabble-score",
|
@@ -85,6 +84,11 @@
|
|
85
84
|
"slug": "triangle",
|
86
85
|
"difficulty": 1,
|
87
86
|
"topics": []
|
87
|
+
},
|
88
|
+
{
|
89
|
+
"slug": "etl",
|
90
|
+
"difficulty": 1,
|
91
|
+
"topics": []
|
88
92
|
}
|
89
93
|
],
|
90
94
|
"deprecated": [],
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"
|
2
|
+
" Version: 1.0.0
|
3
|
+
"
|
4
|
+
|
5
|
+
Before:
|
6
|
+
unlet! input expected
|
7
|
+
|
8
|
+
Execute (a single letter):
|
9
|
+
let input = {'1': ['A']}
|
10
|
+
let expected = {'a': 1}
|
11
|
+
AssertEqual expected, Transform(input)
|
12
|
+
|
13
|
+
Execute (single score with multiple letters):
|
14
|
+
let input = {'1': ['A', 'E', 'I', 'O', 'U']}
|
15
|
+
let expected = {'a': 1, 'e': 1, 'i': 1, 'u': 1, 'o': 1}
|
16
|
+
AssertEqual expected, Transform(input)
|
17
|
+
|
18
|
+
Execute (multiple scores with multiple letters):
|
19
|
+
let input = {'1': ['A', 'E'], '2': ['D', 'G']}
|
20
|
+
let expected = {'a': 1, 'd': 2, 'e': 1, 'g': 2}
|
21
|
+
AssertEqual expected, Transform(input)
|
22
|
+
|
23
|
+
Execute (multiple scores with differing numbers of letters):
|
24
|
+
let input = {'1': ['A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T'], '2': ['D', 'G'], '3': ['B', 'C', 'M', 'P'], '4': ['F', 'H', 'V', 'W', 'Y'], '5': ['K'], '8': ['J', 'X'], '10': ['Q', 'Z']}
|
25
|
+
let expected = {'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, 'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1, 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, 'z': 10}
|
26
|
+
AssertEqual expected, Transform(input)
|
27
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"
|
2
|
+
" We are going to do the Transform step of an Extract-Transform-Load.
|
3
|
+
"
|
4
|
+
" Example:
|
5
|
+
"
|
6
|
+
" :echo Transform({'1': ['a', 'b'], '2': ['c']})
|
7
|
+
" {'a': 1, 'b': 1, 'c': 2}
|
8
|
+
"
|
9
|
+
|
10
|
+
function! Transform(scores) abort
|
11
|
+
" your code goes here
|
12
|
+
endfunction
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trackler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.0.
|
4
|
+
version: 2.1.0.29
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katrina Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -4743,6 +4743,13 @@ files:
|
|
4743
4743
|
- tracks/java/exercises/word-count/src/example/java/WordCount.java
|
4744
4744
|
- tracks/java/exercises/word-count/src/main/java/WordCount.java
|
4745
4745
|
- tracks/java/exercises/word-count/src/test/java/WordCountTest.java
|
4746
|
+
- tracks/java/exercises/word-search/build.gradle
|
4747
|
+
- tracks/java/exercises/word-search/src/example/java/Pair.java
|
4748
|
+
- tracks/java/exercises/word-search/src/example/java/WordLocation.java
|
4749
|
+
- tracks/java/exercises/word-search/src/example/java/WordSearcher.java
|
4750
|
+
- tracks/java/exercises/word-search/src/main/java/Pair.java
|
4751
|
+
- tracks/java/exercises/word-search/src/main/java/WordLocation.java
|
4752
|
+
- tracks/java/exercises/word-search/src/test/java/WordSearcherTest.java
|
4746
4753
|
- tracks/java/exercises/wordy/build.gradle
|
4747
4754
|
- tracks/java/exercises/wordy/src/example/java/WordProblemSolver.java
|
4748
4755
|
- tracks/java/exercises/wordy/src/main/java/WordProblemSolver.java
|
@@ -8321,7 +8328,6 @@ files:
|
|
8321
8328
|
- tracks/scala/exercises/pascals-triangle/src/test/scala/PascalsTriangleTest.scala
|
8322
8329
|
- tracks/scala/exercises/perfect-numbers/build.sbt
|
8323
8330
|
- tracks/scala/exercises/perfect-numbers/example.scala
|
8324
|
-
- tracks/scala/exercises/perfect-numbers/src/main/scala/PerfectNumbers.scala
|
8325
8331
|
- tracks/scala/exercises/perfect-numbers/src/test/scala/PerfectNumbersTest.scala
|
8326
8332
|
- tracks/scala/exercises/phone-number/HINTS.md
|
8327
8333
|
- tracks/scala/exercises/phone-number/build.sbt
|
@@ -8484,6 +8490,7 @@ files:
|
|
8484
8490
|
- tracks/scala/testgen/src/main/scala/LeapTestGenerator.scala
|
8485
8491
|
- tracks/scala/testgen/src/main/scala/NucleotideCountTestGenerator.scala
|
8486
8492
|
- tracks/scala/testgen/src/main/scala/PangramsTestGenerator.scala
|
8493
|
+
- tracks/scala/testgen/src/main/scala/PerfectNumbersTestGenerator.scala
|
8487
8494
|
- tracks/scala/testgen/src/main/scala/RailFenceCipherTestGenerator.scala
|
8488
8495
|
- tracks/scala/testgen/src/main/scala/RaindropsTestGenerator.scala
|
8489
8496
|
- tracks/scala/testgen/src/main/scala/SumOfMultiplesTestGenerator.scala
|
@@ -9275,6 +9282,9 @@ files:
|
|
9275
9282
|
- tracks/vimscript/exercises/difference-of-squares/difference_of_squares.vader
|
9276
9283
|
- tracks/vimscript/exercises/difference-of-squares/difference_of_squares.vim
|
9277
9284
|
- tracks/vimscript/exercises/difference-of-squares/example.vim
|
9285
|
+
- tracks/vimscript/exercises/etl/etl.vader
|
9286
|
+
- tracks/vimscript/exercises/etl/etl.vim
|
9287
|
+
- tracks/vimscript/exercises/etl/example.vim
|
9278
9288
|
- tracks/vimscript/exercises/hamming/example.vim
|
9279
9289
|
- tracks/vimscript/exercises/hamming/hamming.vader
|
9280
9290
|
- tracks/vimscript/exercises/hamming/hamming.vim
|
File without changes
|