trackler 2.0.0.5 → 2.0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/bash/docs/TESTS.md +1 -1
- data/tracks/bash/exercises/bob/bob_test.sh +2 -0
- data/tracks/bash/exercises/gigasecond/gigasecond_test.sh +2 -0
- data/tracks/bash/exercises/hamming/hamming_test.sh +2 -0
- data/tracks/bash/exercises/hello-world/hello_world_test.sh +2 -0
- data/tracks/bash/exercises/leap/leap_test.sh +2 -0
- data/tracks/bash/exercises/raindrops/raindrops_test.sh +2 -0
- data/tracks/bash/exercises/rna-transcription/rna_transcription_test.sh +2 -0
- data/tracks/c/bin/verify-indent +5 -1
- data/tracks/c/config.json +10 -1
- data/tracks/c/exercises/clock/src/clock.h +1 -1
- data/tracks/c/exercises/largest-series-product/test/test_largest_series_product.c +1 -1
- data/tracks/c/exercises/phone-number/src/example.c +4 -2
- data/tracks/c/exercises/roman-numerals/src/example.c +20 -21
- data/tracks/c/exercises/roman-numerals/src/example.h +1 -1
- data/tracks/c/exercises/roman-numerals/test/test_roman_numerals.c +1 -0
- data/tracks/c/exercises/sum-of-multiples/src/example.c +3 -1
- data/tracks/c/exercises/sum-of-multiples/src/example.h +3 -1
- data/tracks/c/exercises/sum-of-multiples/test/test_sum_of_multiples.c +44 -22
- data/tracks/c/exercises/word-count/makefile +16 -0
- data/tracks/c/exercises/word-count/src/example.c +65 -0
- data/tracks/c/exercises/word-count/src/word_count.h +22 -0
- data/tracks/c/exercises/word-count/test/test_word_count.c +372 -0
- data/tracks/c/exercises/word-count/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/word-count/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/word-count/test/vendor/unity_internals.h +701 -0
- data/tracks/crystal/.gitignore +1 -0
- data/tracks/crystal/Makefile +6 -0
- data/tracks/crystal/README.md +25 -0
- data/tracks/crystal/config.json +10 -2
- data/tracks/crystal/exercises/acronym/spec/acronym_spec.cr +32 -0
- data/tracks/crystal/exercises/acronym/src/example.cr +7 -0
- data/tracks/crystal/exercises/hello-world/spec/hello_world_spec.cr +8 -10
- data/tracks/crystal/exercises/hello-world/src/example.cr +1 -1
- data/tracks/crystal/src/generator/exercises/acronym.cr +34 -0
- data/tracks/crystal/src/generator/exercises/exercise_generator.cr +39 -0
- data/tracks/crystal/src/generator/exercises/exercise_test_case.cr +8 -0
- data/tracks/crystal/src/generator/exercises/hello_world.cr +38 -0
- data/tracks/crystal/src/generator/exercises/templates/example.tt +10 -0
- data/tracks/crystal/src/generator/generate.cr +15 -0
- data/tracks/crystal/src/generator/spec/exercise_generator_spec.cr +27 -0
- data/tracks/crystal/src/generator/spec/exercise_test_case_spec.cr +23 -0
- data/tracks/elixir/exercises/space-age/space_age.exs +1 -1
- data/tracks/elm/config.json +5 -31
- data/tracks/elm/elm-package.json +1 -0
- data/tracks/elm/exercises/bob/BobTests.elm +1 -1
- data/tracks/elm/exercises/run-length-encoding/RunLengthEncoding.elm +5 -0
- data/tracks/elm/exercises/scrabble-score/ScrabbleScore.elm +1 -0
- data/tracks/elm/exercises/scrabble-score/ScrabbleScore.example +32 -0
- data/tracks/elm/exercises/scrabble-score/ScrabbleScoreTests.elm +43 -0
- data/tracks/elm/exercises/scrabble-score/elm-package.json +16 -0
- data/tracks/elm/exercises/scrabble-score/runtests.bat +1 -0
- data/tracks/elm/exercises/scrabble-score/runtests.sh +2 -0
- data/tracks/elm/exercises/sublist/Sublist.elm +5 -0
- data/tracks/fsharp/exercises/sum-of-multiples/SumOfMultiplesTest.fs +6 -1
- data/tracks/haskell/docs/LEARNING.md +11 -2
- data/tracks/haskell/exercises/list-ops/test/Tests.hs +2 -0
- data/tracks/java/config.json +13 -1
- data/tracks/java/exercises/etl/src/test/java/EtlTest.java +101 -55
- data/tracks/java/exercises/hello-world/TUTORIAL.md +1 -1
- data/tracks/java/exercises/largest-series-product/build.gradle +17 -0
- data/tracks/java/exercises/largest-series-product/src/example/java/LargestSeriesProductCalculator.java +56 -0
- data/tracks/java/exercises/largest-series-product/src/main/java/LargestSeriesProductCalculator.java +5 -0
- data/tracks/java/exercises/largest-series-product/src/test/java/LargestSeriesProductCalculatorTest.java +218 -0
- data/tracks/java/exercises/queen-attack/build.gradle +17 -0
- data/tracks/java/exercises/queen-attack/src/example/java/BoardCoordinate.java +39 -0
- data/tracks/java/exercises/queen-attack/src/example/java/QueenAttackCalculator.java +54 -0
- data/tracks/java/exercises/queen-attack/src/main/java/BoardCoordinate.java +5 -0
- data/tracks/java/exercises/queen-attack/src/main/java/QueenAttackCalculator.java +5 -0
- data/tracks/java/exercises/queen-attack/src/test/java/QueenAttackCalculatorTest.java +135 -0
- data/tracks/java/exercises/settings.gradle +2 -0
- data/tracks/ocaml/exercises/leap/test.ml +17 -6
- data/tracks/rust/_test/check-exercises.sh +5 -0
- data/tracks/swift/docs/TESTS.md +23 -3
- metadata +35 -2
@@ -1,79 +1,125 @@
|
|
1
|
-
import com.google.common.collect.ImmutableMap;
|
2
1
|
import org.junit.Test;
|
3
|
-
import org.junit.Ignore;
|
4
2
|
|
5
|
-
import java.util
|
6
|
-
|
7
|
-
import
|
3
|
+
import java.util.*;
|
4
|
+
|
5
|
+
import static org.junit.Assert.assertEquals;
|
8
6
|
|
9
|
-
import static org.assertj.core.api.Assertions.assertThat;
|
10
7
|
|
11
8
|
public class EtlTest {
|
12
9
|
private final Etl etl = new Etl();
|
13
10
|
|
14
|
-
|
15
11
|
@Test
|
16
12
|
public void testTransformOneValue() {
|
17
|
-
Map<Integer, List<String>> old =
|
18
|
-
|
13
|
+
Map<Integer, List<String>> old = new HashMap<Integer, List<String>>() {
|
14
|
+
{
|
15
|
+
put(1, Arrays.asList("A"));
|
16
|
+
}
|
17
|
+
};
|
18
|
+
old = Collections.unmodifiableMap(old);
|
19
|
+
|
20
|
+
Map<String, Integer> expected = new HashMap<String, Integer>() {
|
21
|
+
{
|
22
|
+
put("a", 1);
|
23
|
+
}
|
24
|
+
};
|
25
|
+
expected = Collections.unmodifiableMap(expected);
|
19
26
|
|
20
|
-
|
27
|
+
assertEquals(etl.transform(old), expected);
|
21
28
|
}
|
22
29
|
|
23
|
-
@Ignore
|
24
30
|
@Test
|
25
31
|
public void testTransformMoreValues() {
|
26
|
-
Map<Integer, List<String>> old =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
Map<Integer, List<String>> old = new HashMap<Integer, List<String>>() {
|
33
|
+
{
|
34
|
+
put(1, Arrays.asList("A", "E", "I", "O", "U"));
|
35
|
+
}
|
36
|
+
};
|
37
|
+
old = Collections.unmodifiableMap(old);
|
38
|
+
|
39
|
+
Map<String, Integer> expected = new HashMap<String, Integer>() {
|
40
|
+
{
|
41
|
+
put("a", 1);
|
42
|
+
put("e", 1);
|
43
|
+
put("i", 1);
|
44
|
+
put("o", 1);
|
45
|
+
put("u", 1);
|
46
|
+
}
|
47
|
+
};
|
48
|
+
expected = Collections.unmodifiableMap(expected);
|
49
|
+
|
50
|
+
assertEquals(etl.transform(old), expected);
|
38
51
|
}
|
39
52
|
|
40
|
-
@Ignore
|
41
53
|
@Test
|
42
54
|
public void testMoreKeys() {
|
43
|
-
Map<Integer, List<String>> old =
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
+
Map<Integer, List<String>> old = new HashMap<Integer, List<String>>() {
|
56
|
+
{
|
57
|
+
put(1, Arrays.asList("A", "E"));
|
58
|
+
put(2, Arrays.asList("D", "G"));
|
59
|
+
}
|
60
|
+
};
|
61
|
+
old = Collections.unmodifiableMap(old);
|
62
|
+
|
63
|
+
Map<String, Integer> expected = new HashMap<String, Integer>() {
|
64
|
+
{
|
65
|
+
put("a", 1);
|
66
|
+
put("e", 1);
|
67
|
+
put("d", 2);
|
68
|
+
put("g", 2);
|
69
|
+
}
|
70
|
+
};
|
71
|
+
expected = Collections.unmodifiableMap(expected);
|
72
|
+
|
73
|
+
assertEquals(etl.transform(old), expected);
|
55
74
|
}
|
56
75
|
|
57
|
-
@Ignore
|
58
76
|
@Test
|
59
77
|
public void testFullDataset() {
|
60
|
-
Map<Integer, List<String>> old =
|
61
|
-
|
62
|
-
put(
|
63
|
-
put(
|
64
|
-
put(
|
65
|
-
put(
|
66
|
-
put(
|
67
|
-
put(
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
put("
|
76
|
-
|
77
|
-
|
78
|
+
Map<Integer, List<String>> old = new HashMap<Integer, List<String>>() {
|
79
|
+
{
|
80
|
+
put(1, Arrays.asList("A", "E", "I", "O", "U", "L", "N", "R", "S", "T"));
|
81
|
+
put(2, Arrays.asList("D", "G"));
|
82
|
+
put(3, Arrays.asList("B", "C", "M", "P"));
|
83
|
+
put(4, Arrays.asList("F", "H", "V", "W", "Y"));
|
84
|
+
put(5, Arrays.asList("K"));
|
85
|
+
put(8, Arrays.asList("J", "X"));
|
86
|
+
put(10, Arrays.asList("Q", "Z"));
|
87
|
+
}
|
88
|
+
};
|
89
|
+
old = Collections.unmodifiableMap(old);
|
90
|
+
|
91
|
+
Map<String, Integer> expected = new HashMap<String, Integer>() {
|
92
|
+
{
|
93
|
+
put("a", 1);
|
94
|
+
put("b", 3);
|
95
|
+
put("c", 3);
|
96
|
+
put("d", 2);
|
97
|
+
put("e", 1);
|
98
|
+
put("f", 4);
|
99
|
+
put("g", 2);
|
100
|
+
put("h", 4);
|
101
|
+
put("i", 1);
|
102
|
+
put("j", 8);
|
103
|
+
put("k", 5);
|
104
|
+
put("l", 1);
|
105
|
+
put("m", 3);
|
106
|
+
put("n", 1);
|
107
|
+
put("o", 1);
|
108
|
+
put("p", 3);
|
109
|
+
put("q", 10);
|
110
|
+
put("r", 1);
|
111
|
+
put("s", 1);
|
112
|
+
put("t", 1);
|
113
|
+
put("u", 1);
|
114
|
+
put("v", 4);
|
115
|
+
put("w", 4);
|
116
|
+
put("x", 8);
|
117
|
+
put("y", 4);
|
118
|
+
put("z", 10);
|
119
|
+
}
|
120
|
+
};
|
121
|
+
expected = Collections.unmodifiableMap(expected);
|
122
|
+
|
123
|
+
assertEquals(etl.transform(old), expected);
|
78
124
|
}
|
79
125
|
}
|
@@ -419,7 +419,7 @@ for "good" design of software is a big topic. The pursuit of it underlies
|
|
419
419
|
much of what makes up the more valuable conversations on Exercism.
|
420
420
|
|
421
421
|
For now, let's just take a quick review of our solution and see if there's
|
422
|
-
any part of it we'd like to refactor. Refactoring is changing the
|
422
|
+
any part of it we'd like to refactor. Refactoring is changing the way
|
423
423
|
a bit of code reads without changing what it does.
|
424
424
|
|
425
425
|
Right now, the details of detecting whether the caller of `hello()` has
|
@@ -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,56 @@
|
|
1
|
+
public final class LargestSeriesProductCalculator {
|
2
|
+
|
3
|
+
private final String stringToSearch;
|
4
|
+
|
5
|
+
public LargestSeriesProductCalculator(final String stringToSearch) throws IllegalArgumentException {
|
6
|
+
this.stringToSearch = stringToSearch;
|
7
|
+
validateStringToSearch();
|
8
|
+
}
|
9
|
+
|
10
|
+
public long calculateLargestProductForSeriesLength(final int seriesLength) throws IllegalArgumentException {
|
11
|
+
if (seriesLength < 0) {
|
12
|
+
throw new IllegalArgumentException("Series length must be non-negative.");
|
13
|
+
} else if (seriesLength == 0) {
|
14
|
+
return 1;
|
15
|
+
} else if (seriesLength > stringToSearch.length()) {
|
16
|
+
throw new IllegalArgumentException(
|
17
|
+
"Series length must be less than or equal to the length of the string to search.");
|
18
|
+
} else {
|
19
|
+
long result = 0;
|
20
|
+
|
21
|
+
int numberOfSeriesToCheck = stringToSearch.length() - seriesLength + 1;
|
22
|
+
|
23
|
+
for (int startIndex = 0; startIndex < numberOfSeriesToCheck; startIndex++) {
|
24
|
+
/*
|
25
|
+
* Note: computing the product of each series fresh each time is not the most efficient solution, but
|
26
|
+
* it's the simplest to reason about.
|
27
|
+
*/
|
28
|
+
result = Math.max(result, computeProductOfSeries(startIndex, seriesLength));
|
29
|
+
}
|
30
|
+
|
31
|
+
return result;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
private void validateStringToSearch() throws IllegalArgumentException {
|
36
|
+
if (stringToSearch == null) {
|
37
|
+
throw new IllegalArgumentException("String to search must be non-null.");
|
38
|
+
} else if (!stringToSearch.chars().allMatch(Character::isDigit)) {
|
39
|
+
throw new IllegalArgumentException("String to search may only contains digits.");
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
private long computeProductOfSeries(final int startIndex, final int seriesLength) {
|
44
|
+
// The multiplicative identity is 1.
|
45
|
+
long result = 1;
|
46
|
+
|
47
|
+
final int endIndex = startIndex + seriesLength - 1;
|
48
|
+
|
49
|
+
for (int characterIndex = startIndex; characterIndex <= endIndex; characterIndex++) {
|
50
|
+
result = result * Character.getNumericValue(stringToSearch.charAt(characterIndex));
|
51
|
+
}
|
52
|
+
|
53
|
+
return result;
|
54
|
+
}
|
55
|
+
|
56
|
+
}
|
@@ -0,0 +1,218 @@
|
|
1
|
+
import org.junit.Ignore;
|
2
|
+
import org.junit.Rule;
|
3
|
+
import org.junit.Test;
|
4
|
+
import org.junit.rules.ExpectedException;
|
5
|
+
|
6
|
+
import static org.junit.Assert.assertEquals;
|
7
|
+
|
8
|
+
public final class LargestSeriesProductCalculatorTest {
|
9
|
+
|
10
|
+
/*
|
11
|
+
* See https://github.com/junit-team/junit4/wiki/Rules for information on JUnit Rules in general and
|
12
|
+
* ExpectedExceptions in particular.
|
13
|
+
*/
|
14
|
+
@Rule
|
15
|
+
public ExpectedException expectedException = ExpectedException.none();
|
16
|
+
|
17
|
+
@Test
|
18
|
+
public void testCorrectlyCalculatesLargestProductOfLengthTwoWithNumbersInOrder() {
|
19
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("0123456789");
|
20
|
+
final long expectedProduct = 72;
|
21
|
+
|
22
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(2);
|
23
|
+
|
24
|
+
assertEquals(expectedProduct, actualProduct);
|
25
|
+
}
|
26
|
+
|
27
|
+
@Ignore
|
28
|
+
@Test
|
29
|
+
public void testCorrectlyCalculatesLargestProductOfLengthTwoWithNumbersNotInOrder() {
|
30
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("576802143");
|
31
|
+
final long expectedProduct = 48;
|
32
|
+
|
33
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(2);
|
34
|
+
|
35
|
+
assertEquals(expectedProduct, actualProduct);
|
36
|
+
}
|
37
|
+
|
38
|
+
@Ignore
|
39
|
+
@Test
|
40
|
+
public void testCorrectlyCalculatesLargestProductWhenSeriesLengthEqualsStringToSearchLength() {
|
41
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("29");
|
42
|
+
final long expectedProduct = 18;
|
43
|
+
|
44
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(2);
|
45
|
+
|
46
|
+
assertEquals(expectedProduct, actualProduct);
|
47
|
+
}
|
48
|
+
|
49
|
+
@Ignore
|
50
|
+
@Test
|
51
|
+
public void testCorrectlyCalculatesLargestProductOfLengthThreeWithNumbersInOrder() {
|
52
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("0123456789");
|
53
|
+
final long expectedProduct = 504;
|
54
|
+
|
55
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(3);
|
56
|
+
|
57
|
+
assertEquals(expectedProduct, actualProduct);
|
58
|
+
}
|
59
|
+
|
60
|
+
@Ignore
|
61
|
+
@Test
|
62
|
+
public void testCorrectlyCalculatesLargestProductOfLengthThreeWithNumbersNotInOrder() {
|
63
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("1027839564");
|
64
|
+
final long expectedProduct = 270;
|
65
|
+
|
66
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(3);
|
67
|
+
|
68
|
+
assertEquals(expectedProduct, actualProduct);
|
69
|
+
}
|
70
|
+
|
71
|
+
@Ignore
|
72
|
+
@Test
|
73
|
+
public void testCorrectlyCalculatesLargestProductOfLengthFiveWithNumbersInOrder() {
|
74
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("0123456789");
|
75
|
+
final long expectedProduct = 15120;
|
76
|
+
|
77
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(5);
|
78
|
+
|
79
|
+
assertEquals(expectedProduct, actualProduct);
|
80
|
+
}
|
81
|
+
|
82
|
+
@Ignore
|
83
|
+
@Test
|
84
|
+
public void testCorrectlyCalculatesLargestProductInLongStringToSearchV1() {
|
85
|
+
final LargestSeriesProductCalculator calculator
|
86
|
+
= new LargestSeriesProductCalculator("73167176531330624919225119674426574742355349194934");
|
87
|
+
|
88
|
+
final long expectedProduct = 23520;
|
89
|
+
|
90
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(6);
|
91
|
+
|
92
|
+
assertEquals(expectedProduct, actualProduct);
|
93
|
+
}
|
94
|
+
|
95
|
+
@Ignore
|
96
|
+
@Test
|
97
|
+
public void testCorrectlyCalculatesLargestProductInLongStringToSearchV2() {
|
98
|
+
final LargestSeriesProductCalculator calculator
|
99
|
+
= new LargestSeriesProductCalculator("52677741234314237566414902593461595376319419139427");
|
100
|
+
|
101
|
+
final long expectedProduct = 28350;
|
102
|
+
|
103
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(6);
|
104
|
+
|
105
|
+
assertEquals(expectedProduct, actualProduct);
|
106
|
+
}
|
107
|
+
|
108
|
+
@Ignore
|
109
|
+
@Test
|
110
|
+
public void testCorrectlyCalculatesLargestProductInLongStringToSearchFromProjectEuler() {
|
111
|
+
final LargestSeriesProductCalculator calculator
|
112
|
+
= new LargestSeriesProductCalculator("7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450");
|
113
|
+
|
114
|
+
final long expectedProduct = 23514624000L;
|
115
|
+
|
116
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(13);
|
117
|
+
|
118
|
+
assertEquals(expectedProduct, actualProduct);
|
119
|
+
}
|
120
|
+
|
121
|
+
@Ignore
|
122
|
+
@Test
|
123
|
+
public void testCorrectlyCalculatesLargestProductOfZeroIfAllDigitsAreZeroes() {
|
124
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("0000");
|
125
|
+
final long expectedProduct = 0;
|
126
|
+
|
127
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(2);
|
128
|
+
|
129
|
+
assertEquals(expectedProduct, actualProduct);
|
130
|
+
}
|
131
|
+
|
132
|
+
@Ignore
|
133
|
+
@Test
|
134
|
+
public void testCorrectlyCalculatesLargestProductOfZeroIfAllSeriesOfGivenLengthContainZero() {
|
135
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("99099");
|
136
|
+
final long expectedProduct = 0;
|
137
|
+
|
138
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(3);
|
139
|
+
|
140
|
+
assertEquals(expectedProduct, actualProduct);
|
141
|
+
}
|
142
|
+
|
143
|
+
@Ignore
|
144
|
+
@Test
|
145
|
+
public void testSeriesLengthLongerThanLengthOfStringToTestIsRejected() {
|
146
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("123");
|
147
|
+
|
148
|
+
expectedException.expect(IllegalArgumentException.class);
|
149
|
+
expectedException.expectMessage(
|
150
|
+
"Series length must be less than or equal to the length of the string to search.");
|
151
|
+
|
152
|
+
calculator.calculateLargestProductForSeriesLength(4);
|
153
|
+
}
|
154
|
+
|
155
|
+
@Ignore
|
156
|
+
@Test
|
157
|
+
public void testCorrectlyCalculatesLargestProductOfLength0ForEmptyStringToSearch() {
|
158
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("");
|
159
|
+
final long expectedProduct = 1;
|
160
|
+
|
161
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(0);
|
162
|
+
|
163
|
+
assertEquals(expectedProduct, actualProduct);
|
164
|
+
}
|
165
|
+
|
166
|
+
@Ignore
|
167
|
+
@Test
|
168
|
+
public void testCorrectlyCalculatesLargestProductOfLength0ForNonEmptyStringToSearch() {
|
169
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("123");
|
170
|
+
final long expectedProduct = 1;
|
171
|
+
|
172
|
+
final long actualProduct = calculator.calculateLargestProductForSeriesLength(0);
|
173
|
+
|
174
|
+
assertEquals(expectedProduct, actualProduct);
|
175
|
+
}
|
176
|
+
|
177
|
+
@Ignore
|
178
|
+
@Test
|
179
|
+
public void testEmptyStringToSearchAndSeriesOfNonZeroLengthIsRejected() {
|
180
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("");
|
181
|
+
|
182
|
+
expectedException.expect(IllegalArgumentException.class);
|
183
|
+
expectedException.expectMessage(
|
184
|
+
"Series length must be less than or equal to the length of the string to search.");
|
185
|
+
|
186
|
+
calculator.calculateLargestProductForSeriesLength(1);
|
187
|
+
}
|
188
|
+
|
189
|
+
@Ignore
|
190
|
+
@Test
|
191
|
+
public void testStringToSearchContainingNonDigitCharacterIsRejected() {
|
192
|
+
expectedException.expect(IllegalArgumentException.class);
|
193
|
+
expectedException.expectMessage("String to search may only contains digits.");
|
194
|
+
|
195
|
+
new LargestSeriesProductCalculator("1234a5");
|
196
|
+
}
|
197
|
+
|
198
|
+
@Ignore
|
199
|
+
@Test
|
200
|
+
public void testNegativeSeriesLengthIsRejected() {
|
201
|
+
final LargestSeriesProductCalculator calculator = new LargestSeriesProductCalculator("12345");
|
202
|
+
|
203
|
+
expectedException.expect(IllegalArgumentException.class);
|
204
|
+
expectedException.expectMessage("Series length must be non-negative.");
|
205
|
+
|
206
|
+
calculator.calculateLargestProductForSeriesLength(-1);
|
207
|
+
}
|
208
|
+
|
209
|
+
@Ignore
|
210
|
+
@Test
|
211
|
+
public void testNullStringToSearchIsRejected() {
|
212
|
+
expectedException.expect(IllegalArgumentException.class);
|
213
|
+
expectedException.expectMessage("String to search must be non-null.");
|
214
|
+
|
215
|
+
new LargestSeriesProductCalculator(null);
|
216
|
+
}
|
217
|
+
|
218
|
+
}
|
@@ -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,39 @@
|
|
1
|
+
public final class BoardCoordinate {
|
2
|
+
|
3
|
+
private final int rank;
|
4
|
+
|
5
|
+
private final int file;
|
6
|
+
|
7
|
+
public BoardCoordinate(final int rank, final int file) throws IllegalArgumentException {
|
8
|
+
this.rank = rank;
|
9
|
+
this.file = file;
|
10
|
+
|
11
|
+
validateInputs();
|
12
|
+
}
|
13
|
+
|
14
|
+
public int getRank() {
|
15
|
+
return rank;
|
16
|
+
}
|
17
|
+
|
18
|
+
public int getFile() {
|
19
|
+
return file;
|
20
|
+
}
|
21
|
+
|
22
|
+
private void validateInputs() throws IllegalArgumentException {
|
23
|
+
validateCoordinateComponent(rank, "rank");
|
24
|
+
validateCoordinateComponent(file, "file");
|
25
|
+
}
|
26
|
+
|
27
|
+
private void validateCoordinateComponent(final int value, final String componentName)
|
28
|
+
throws IllegalArgumentException {
|
29
|
+
|
30
|
+
if (value < 0) {
|
31
|
+
throw new IllegalArgumentException("Coordinate must have positive " + componentName + ".");
|
32
|
+
}
|
33
|
+
|
34
|
+
if (value > 7) {
|
35
|
+
throw new IllegalArgumentException("Coordinate must have " + componentName + " <= 7.");
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
public final class QueenAttackCalculator {
|
2
|
+
|
3
|
+
private final BoardCoordinate whiteQueenCoordinate;
|
4
|
+
|
5
|
+
private final BoardCoordinate blackQueenCoordinate;
|
6
|
+
|
7
|
+
public QueenAttackCalculator(final BoardCoordinate whiteQueenCoordinate, final BoardCoordinate blackQueenCoordinate)
|
8
|
+
throws IllegalArgumentException {
|
9
|
+
|
10
|
+
this.whiteQueenCoordinate = whiteQueenCoordinate;
|
11
|
+
this.blackQueenCoordinate = blackQueenCoordinate;
|
12
|
+
|
13
|
+
validateInputs();
|
14
|
+
}
|
15
|
+
|
16
|
+
public boolean canQueensAttackOneAnother() {
|
17
|
+
return queensShareFile() || queensShareRank() || queensShareDiagonal();
|
18
|
+
}
|
19
|
+
|
20
|
+
private void validateInputs() throws IllegalArgumentException {
|
21
|
+
if (whiteQueenCoordinate == null || blackQueenCoordinate == null) {
|
22
|
+
throw new IllegalArgumentException("You must supply valid board coordinates for both Queens.");
|
23
|
+
}
|
24
|
+
|
25
|
+
if (queensShareBoardCoordinate()) {
|
26
|
+
throw new IllegalArgumentException("Queens may not occupy the same board coordinate.");
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
private boolean queensShareRank() {
|
31
|
+
return differenceBetweenRanks() == 0;
|
32
|
+
}
|
33
|
+
|
34
|
+
private boolean queensShareFile() {
|
35
|
+
return differenceBetweenFiles() == 0;
|
36
|
+
}
|
37
|
+
|
38
|
+
private boolean queensShareBoardCoordinate() {
|
39
|
+
return queensShareRank() && queensShareFile();
|
40
|
+
}
|
41
|
+
|
42
|
+
private boolean queensShareDiagonal() {
|
43
|
+
return differenceBetweenRanks() == differenceBetweenFiles();
|
44
|
+
}
|
45
|
+
|
46
|
+
private int differenceBetweenRanks() {
|
47
|
+
return Math.abs(whiteQueenCoordinate.getRank() - blackQueenCoordinate.getRank());
|
48
|
+
}
|
49
|
+
|
50
|
+
private int differenceBetweenFiles() {
|
51
|
+
return Math.abs(whiteQueenCoordinate.getFile() - blackQueenCoordinate.getFile());
|
52
|
+
}
|
53
|
+
|
54
|
+
}
|