trackler 2.2.1.52 → 2.2.1.53

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.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/problem-specifications/exercises/leap/canonical-data.json +2 -2
  4. data/tracks/cfml/tasks/FormatConfig.cfc +6 -4
  5. data/tracks/cfml/tasks/GenerateReadme.cfc +197 -0
  6. data/tracks/cfml/tasks/ScaffoldExercise.cfc +6 -0
  7. data/tracks/csharp/config.json +1 -1
  8. data/tracks/delphi/exercises/leap/uLeapTests.pas +1 -1
  9. data/tracks/fsharp/exercises/clock/Clock.fs +1 -1
  10. data/tracks/fsharp/exercises/clock/ClockTest.fs +239 -61
  11. data/tracks/fsharp/exercises/clock/Example.fs +3 -3
  12. data/tracks/fsharp/exercises/dominoes/DominoesTest.fs +29 -26
  13. data/tracks/fsharp/exercises/largest-series-product/LargestSeriesProductTest.fs +30 -15
  14. data/tracks/fsharp/exercises/leap/LeapTest.fs +2 -2
  15. data/tracks/fsharp/exercises/rectangles/Example.fs +1 -1
  16. data/tracks/fsharp/exercises/rectangles/Rectangles.fs +1 -1
  17. data/tracks/fsharp/exercises/rectangles/RectanglesTest.fs +66 -43
  18. data/tracks/fsharp/generators/Generators.fs +85 -1
  19. data/tracks/java/scripts/canonical_data_check.sh +8 -0
  20. data/tracks/kotlin/.gitignore +1 -0
  21. data/tracks/kotlin/exercises/acronym/.meta/version +1 -0
  22. data/tracks/kotlin/exercises/acronym/src/test/kotlin/AcronymTest.kt +9 -10
  23. data/tracks/kotlin/exercises/all-your-base/.meta/version +1 -1
  24. data/tracks/kotlin/exercises/all-your-base/src/test/kotlin/BaseConverterTest.kt +20 -20
  25. data/tracks/kotlin/exercises/allergies/.meta/version +1 -0
  26. data/tracks/kotlin/exercises/allergies/src/test/kotlin/AllergiesTest.kt +19 -72
  27. data/tracks/kotlin/exercises/anagram/.meta/src/reference/kotlin/Anagram.kt +7 -4
  28. data/tracks/kotlin/exercises/anagram/.meta/version +1 -0
  29. data/tracks/kotlin/exercises/anagram/src/test/kotlin/AnagramTest.kt +76 -29
  30. data/tracks/kotlin/exercises/atbash-cipher/.meta/version +1 -0
  31. data/tracks/kotlin/exercises/atbash-cipher/src/test/kotlin/AtbashTest.kt +6 -3
  32. data/tracks/kotlin/exercises/beer-song/.meta/version +1 -0
  33. data/tracks/kotlin/exercises/beer-song/src/test/kotlin/BeerSongTest.kt +21 -46
  34. data/tracks/kotlin/exercises/binary-search/.meta/version +1 -0
  35. data/tracks/kotlin/exercises/binary-search/src/test/kotlin/BinarySearchTest.kt +30 -19
  36. data/tracks/kotlin/exercises/bob/.meta/src/reference/kotlin/Bob.kt +8 -7
  37. data/tracks/kotlin/exercises/bob/.meta/version +1 -0
  38. data/tracks/kotlin/exercises/bob/src/test/kotlin/BobTest.kt +57 -15
  39. data/tracks/kotlin/exercises/bracket-push/.meta/version +1 -0
  40. data/tracks/kotlin/exercises/bracket-push/src/test/kotlin/BracketPushTest.kt +3 -1
  41. data/tracks/kotlin/exercises/collatz-conjecture/.meta/version +1 -1
  42. data/tracks/kotlin/exercises/difference-of-squares/.meta/version +1 -0
  43. data/tracks/kotlin/exercises/difference-of-squares/src/test/kotlin/SquaresTest.kt +10 -23
  44. data/tracks/kotlin/exercises/etl/.meta/src/reference/kotlin/ETL.kt +7 -1
  45. data/tracks/kotlin/exercises/etl/.meta/version +1 -0
  46. data/tracks/kotlin/exercises/etl/src/test/kotlin/ETLTest.kt +10 -10
  47. data/tracks/kotlin/exercises/flatten-array/.meta/version +1 -0
  48. data/tracks/kotlin/exercises/flatten-array/src/test/kotlin/FlattenerTest.kt +8 -16
  49. data/tracks/kotlin/exercises/gigasecond/.meta/version +1 -0
  50. data/tracks/kotlin/exercises/gigasecond/src/test/kotlin/GigasecondTest.kt +1 -1
  51. data/tracks/kotlin/exercises/hamming/.meta/src/reference/kotlin/Hamming.kt +1 -1
  52. data/tracks/kotlin/exercises/hamming/.meta/version +1 -1
  53. data/tracks/kotlin/exercises/hamming/src/test/kotlin/HammingTest.kt +4 -4
  54. data/tracks/kotlin/exercises/hello-world/.meta/version +1 -0
  55. data/tracks/kotlin/exercises/hello-world/src/test/kotlin/HelloWorldTest.kt +1 -1
  56. data/tracks/kotlin/exercises/isogram/.meta/version +1 -0
  57. data/tracks/kotlin/exercises/isogram/src/test/kotlin/IsogramTest.kt +5 -8
  58. data/tracks/kotlin/exercises/largest-series-product/.meta/src/reference/kotlin/Series.kt +2 -3
  59. data/tracks/kotlin/exercises/largest-series-product/.meta/version +1 -0
  60. data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesTest.kt +97 -0
  61. data/tracks/kotlin/exercises/leap/.meta/version +1 -0
  62. data/tracks/kotlin/exercises/leap/src/test/kotlin/LeapTest.kt +8 -26
  63. data/tracks/kotlin/exercises/list-ops/.meta/version +1 -1
  64. data/tracks/kotlin/exercises/luhn/.meta/version +1 -0
  65. data/tracks/kotlin/exercises/luhn/src/test/kotlin/LuhnTest.kt +0 -3
  66. data/tracks/kotlin/exercises/nth-prime/.meta/version +1 -0
  67. data/tracks/kotlin/exercises/nth-prime/src/test/kotlin/PrimeTest.kt +0 -2
  68. data/tracks/kotlin/exercises/nucleotide-count/.meta/src/reference/kotlin/{DNA.kt → Dna.kt} +3 -8
  69. data/tracks/kotlin/exercises/nucleotide-count/.meta/version +1 -0
  70. data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/DnaTest.kt +48 -0
  71. data/tracks/kotlin/exercises/pangram/.meta/src/reference/kotlin/{Pangrams.kt → Pangram.kt} +1 -1
  72. data/tracks/kotlin/exercises/pangram/.meta/version +1 -1
  73. data/tracks/kotlin/exercises/pangram/src/test/kotlin/PangramTest.kt +15 -9
  74. data/tracks/kotlin/exercises/pascals-triangle/.meta/version +1 -0
  75. data/tracks/kotlin/exercises/pascals-triangle/src/test/kotlin/PascalsTriangleTest.kt +32 -14
  76. data/tracks/kotlin/exercises/perfect-numbers/.meta/src/reference/kotlin/NaturalNumber.kt +1 -1
  77. data/tracks/kotlin/exercises/perfect-numbers/.meta/version +1 -0
  78. data/tracks/kotlin/exercises/perfect-numbers/src/test/kotlin/{PerfectNumbersTest.kt → NaturalNumberTest.kt} +25 -7
  79. data/tracks/kotlin/exercises/phone-number/.meta/src/reference/kotlin/PhoneNumber.kt +15 -7
  80. data/tracks/kotlin/exercises/phone-number/.meta/version +1 -0
  81. data/tracks/kotlin/exercises/phone-number/src/test/kotlin/PhoneNumberTest.kt +46 -29
  82. data/tracks/kotlin/exercises/pig-latin/.meta/src/reference/kotlin/PigLatin.kt +2 -2
  83. data/tracks/kotlin/exercises/pig-latin/.meta/version +1 -0
  84. data/tracks/kotlin/exercises/pig-latin/src/test/kotlin/PigLatinTest.kt +21 -10
  85. data/tracks/kotlin/exercises/raindrops/.meta/version +1 -0
  86. data/tracks/kotlin/exercises/raindrops/src/test/kotlin/RaindropsTest.kt +19 -26
  87. data/tracks/kotlin/exercises/react/.meta/version +1 -0
  88. data/tracks/kotlin/exercises/react/src/test/kotlin/ReactTest.kt +11 -4
  89. data/tracks/kotlin/exercises/robot-simulator/.meta/version +1 -1
  90. data/tracks/kotlin/exercises/roman-numerals/.meta/version +1 -0
  91. data/tracks/kotlin/exercises/roman-numerals/src/test/kotlin/RomanNumeralTest.kt +1 -2
  92. data/tracks/kotlin/exercises/rotational-cipher/.meta/version +1 -1
  93. data/tracks/kotlin/exercises/rotational-cipher/src/test/kotlin/RotationalCipherTest.kt +7 -7
  94. data/tracks/kotlin/exercises/scrabble-score/.meta/src/reference/kotlin/{Scrabble.kt → ScrabbleScore.kt} +1 -1
  95. data/tracks/kotlin/exercises/scrabble-score/.meta/version +1 -0
  96. data/tracks/kotlin/exercises/scrabble-score/src/test/kotlin/ScrabbleScoreTest.kt +9 -7
  97. data/tracks/kotlin/exercises/sieve/.meta/version +1 -0
  98. data/tracks/kotlin/exercises/sieve/src/test/kotlin/SieveTest.kt +8 -0
  99. data/tracks/kotlin/exercises/space-age/.meta/version +1 -0
  100. data/tracks/kotlin/exercises/space-age/src/test/kotlin/SpaceAgeTest.kt +1 -16
  101. data/tracks/kotlin/exercises/sum-of-multiples/.meta/version +1 -0
  102. data/tracks/kotlin/exercises/sum-of-multiples/src/test/kotlin/SumOfMultiplesTest.kt +7 -7
  103. data/tracks/kotlin/exercises/triangle/.meta/version +1 -0
  104. data/tracks/kotlin/exercises/two-fer/.meta/version +1 -0
  105. data/tracks/kotlin/exercises/two-fer/src/test/kotlin/TwoferTest.kt +0 -1
  106. data/tracks/kotlin/exercises/word-count/.meta/src/reference/kotlin/WordCount.kt +6 -2
  107. data/tracks/kotlin/exercises/word-count/.meta/version +1 -0
  108. data/tracks/kotlin/exercises/word-count/src/test/kotlin/WordCountTest.kt +31 -9
  109. data/tracks/kotlin/scripts/canonical_data_check.sh +8 -0
  110. data/tracks/perl6/exercises/leap/leap.t +2 -2
  111. data/tracks/php/config.json +16 -0
  112. data/tracks/php/exercises/crypto-square/crypto-square_test.php +50 -0
  113. data/tracks/php/exercises/crypto-square/example.php +32 -0
  114. data/tracks/php/exercises/meetup/README.md +21 -0
  115. data/tracks/php/exercises/meetup/example.php +19 -0
  116. data/tracks/php/exercises/meetup/meetup_test.php +577 -0
  117. data/tracks/python/README.md +7 -5
  118. data/tracks/python/config.json +36 -27
  119. data/tracks/python/docs/TESTS.md +36 -12
  120. data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +1 -1
  121. data/tracks/python/exercises/diffie-hellman/.meta/hints.md +16 -0
  122. data/tracks/python/exercises/diffie-hellman/README.md +15 -2
  123. data/tracks/python/exercises/error-handling/README.md +23 -0
  124. data/tracks/python/exercises/error-handling/error_handling.py +14 -0
  125. data/tracks/python/exercises/error-handling/error_handling_test.py +66 -0
  126. data/tracks/python/exercises/error-handling/example.py +21 -0
  127. data/tracks/python/exercises/forth/forth_test.py +1 -1
  128. data/tracks/python/exercises/isogram/isogram_test.py +5 -3
  129. data/tracks/python/exercises/leap/leap_test.py +2 -2
  130. data/tracks/python/exercises/rotational-cipher/rotational_cipher_test.py +4 -4
  131. data/tracks/python/exercises/simple-cipher/.meta/hints.md +16 -0
  132. data/tracks/python/exercises/simple-cipher/README.md +17 -0
  133. data/tracks/python/exercises/sum-of-multiples/sum_of_multiples_test.py +4 -1
  134. data/tracks/python/exercises/twelve-days/example.py +3 -3
  135. data/tracks/python/exercises/twelve-days/twelve_days.py +2 -2
  136. metadata +53 -9
  137. data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesInvalidInputTest.kt +0 -30
  138. data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesValidInputTest.kt +0 -34
  139. data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/NucleotideTest.kt +0 -87
@@ -62,6 +62,7 @@ then
62
62
  fi
63
63
 
64
64
  track_exercise_slugs=$(jq '.exercises[] | select(has("deprecated") | not) | .slug' $config_file_path | tr -d "\"")
65
+ update_needed_count=0
65
66
 
66
67
  for slug in $track_exercise_slugs
67
68
  do
@@ -88,6 +89,7 @@ do
88
89
  if ! [ -f "$track_exercise_version_file_path" ]
89
90
  then
90
91
  echo "$slug: needs update or version file (v$canonical_data_version)."
92
+ update_needed_count=$((update_needed_count + 1))
91
93
  continue
92
94
  fi
93
95
 
@@ -98,7 +100,13 @@ do
98
100
  # echo "$slug: up-to-date."
99
101
  continue
100
102
  else
103
+ update_needed_count=$((update_needed_count + 1))
101
104
  echo "$slug: needs update (v$track_data_version -> v$canonical_data_version)."
102
105
  fi
103
106
 
104
107
  done
108
+
109
+ if [ $update_needed_count -eq 1 ]
110
+ then
111
+ echo "All exercises are up to date!"
112
+ fi
@@ -7,3 +7,4 @@ build
7
7
  .gradle
8
8
  .idea
9
9
  *.iml
10
+ out/
@@ -4,7 +4,6 @@ import kotlin.test.assertEquals
4
4
 
5
5
  class AcronymTest {
6
6
 
7
-
8
7
  @Test
9
8
  fun fromTitleCasedPhrases() {
10
9
  val phrase = "Portable Network Graphics"
@@ -20,14 +19,6 @@ class AcronymTest {
20
19
  assertEquals(expected, Acronym.generate(phrase))
21
20
  }
22
21
 
23
- @Ignore
24
- @Test
25
- fun fromInconsistentlyCasedPhrases() {
26
- val phrase = "HyperText Markup Language"
27
- val expected = "HTML"
28
- assertEquals(expected, Acronym.generate(phrase))
29
- }
30
-
31
22
  @Ignore
32
23
  @Test
33
24
  fun fromPhrasesWithPunctuation() {
@@ -38,12 +29,20 @@ class AcronymTest {
38
29
 
39
30
  @Ignore
40
31
  @Test
41
- fun fromOtherPhrasesWithPunctuation() {
32
+ fun fromAllCapsWord() {
42
33
  val phrase = "PHP: Hypertext Preprocessor"
43
34
  val expected = "PHP"
44
35
  assertEquals(expected, Acronym.generate(phrase))
45
36
  }
46
37
 
38
+ @Ignore
39
+ @Test
40
+ fun fromNonAcronymAllCapsWord() {
41
+ val phrase = "GNU Image Manipulation Program"
42
+ val expected = "GIMP"
43
+ assertEquals(expected, Acronym.generate(phrase))
44
+ }
45
+
47
46
  @Ignore
48
47
  @Test
49
48
  fun fromPhrasesWithPunctuationAndSentenceCasing() {
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.1.0
@@ -168,69 +168,69 @@ class BaseConverterTest {
168
168
 
169
169
  @Ignore
170
170
  @Test
171
- fun testNegativeDigit() {
171
+ fun testFirstBaseIsOne() {
172
172
  expectedException.expect(IllegalArgumentException::class.java)
173
- expectedException.expectMessage("Digits may not be negative.")
173
+ expectedException.expectMessage("Bases must be at least 2.")
174
174
 
175
- BaseConverter(2, intArrayOf(1, -1, 1, 0, 1, 0))
175
+ BaseConverter(1, intArrayOf())
176
176
  }
177
177
 
178
178
  @Ignore
179
179
  @Test
180
- fun testInvalidPositiveDigit() {
180
+ fun testFirstBaseIsZero() {
181
181
  expectedException.expect(IllegalArgumentException::class.java)
182
- expectedException.expectMessage("All digits must be strictly less than the base.")
182
+ expectedException.expectMessage("Bases must be at least 2.")
183
183
 
184
- BaseConverter(2, intArrayOf(1, 2, 1, 0, 1, 0))
184
+ BaseConverter(0, intArrayOf())
185
185
  }
186
186
 
187
187
  @Ignore
188
188
  @Test
189
- fun testFirstBaseIsOne() {
189
+ fun testFirstBaseIsNegative() {
190
190
  expectedException.expect(IllegalArgumentException::class.java)
191
191
  expectedException.expectMessage("Bases must be at least 2.")
192
192
 
193
- BaseConverter(1, intArrayOf())
193
+ BaseConverter(-2, intArrayOf())
194
194
  }
195
195
 
196
196
  @Ignore
197
197
  @Test
198
- fun testSecondBaseIsOne() {
199
- val baseConverter = BaseConverter(2, intArrayOf(1, 0, 1, 0, 1, 0))
200
-
198
+ fun testNegativeDigit() {
201
199
  expectedException.expect(IllegalArgumentException::class.java)
202
- expectedException.expectMessage("Bases must be at least 2.")
200
+ expectedException.expectMessage("Digits may not be negative.")
203
201
 
204
- baseConverter.convertToBase(1)
202
+ BaseConverter(2, intArrayOf(1, -1, 1, 0, 1, 0))
205
203
  }
206
204
 
207
205
  @Ignore
208
206
  @Test
209
- fun testFirstBaseIsZero() {
207
+ fun testInvalidPositiveDigit() {
210
208
  expectedException.expect(IllegalArgumentException::class.java)
211
- expectedException.expectMessage("Bases must be at least 2.")
209
+ expectedException.expectMessage("All digits must be strictly less than the base.")
212
210
 
213
- BaseConverter(0, intArrayOf())
211
+ BaseConverter(2, intArrayOf(1, 2, 1, 0, 1, 0))
214
212
  }
215
213
 
216
214
  @Ignore
217
215
  @Test
218
- fun testSecondBaseIsZero() {
216
+ fun testSecondBaseIsOne() {
219
217
  val baseConverter = BaseConverter(2, intArrayOf(1, 0, 1, 0, 1, 0))
220
218
 
221
219
  expectedException.expect(IllegalArgumentException::class.java)
222
220
  expectedException.expectMessage("Bases must be at least 2.")
223
221
 
224
- baseConverter.convertToBase(0)
222
+ baseConverter.convertToBase(1)
225
223
  }
226
224
 
227
225
  @Ignore
228
226
  @Test
229
- fun testFirstBaseIsNegative() {
227
+ fun testSecondBaseIsZero() {
228
+ val baseConverter = BaseConverter(2, intArrayOf(1, 0, 1, 0, 1, 0))
229
+
230
230
  expectedException.expect(IllegalArgumentException::class.java)
231
231
  expectedException.expectMessage("Bases must be at least 2.")
232
232
 
233
- BaseConverter(-2, intArrayOf())
233
+ baseConverter.convertToBase(0)
234
234
  }
235
235
 
236
236
  @Ignore
@@ -1,18 +1,18 @@
1
1
  import org.junit.Test
2
2
  import org.junit.Ignore
3
3
  import kotlin.test.assertEquals
4
+ import kotlin.test.assertFalse
5
+ import kotlin.test.assertTrue
4
6
 
5
7
  class AllergiesTest {
6
8
 
7
-
8
9
  @Test
9
10
  fun noAllergiesMeansNotAllergicToAnything() {
10
11
  val allergies = Allergies(0)
11
12
 
12
- assertEquals(false, allergies.isAllergicTo(Allergen.EGGS))
13
- assertEquals(false, allergies.isAllergicTo(Allergen.PEANUTS))
14
- assertEquals(false, allergies.isAllergicTo(Allergen.STRAWBERRIES))
15
- assertEquals(false, allergies.isAllergicTo(Allergen.CATS))
13
+ assertFalse(allergies.isAllergicTo(Allergen.PEANUTS))
14
+ assertFalse(allergies.isAllergicTo(Allergen.CATS))
15
+ assertFalse(allergies.isAllergicTo(Allergen.STRAWBERRIES))
16
16
  }
17
17
 
18
18
  @Ignore
@@ -20,71 +20,17 @@ class AllergiesTest {
20
20
  fun allergicToEggs() {
21
21
  val allergies = Allergies(1)
22
22
 
23
- assertEquals(true, allergies.isAllergicTo(Allergen.EGGS))
24
- }
25
-
26
- @Ignore
27
- @Test
28
- fun allergicToPeanuts() {
29
- val allergies = Allergies(2)
30
-
31
- assertEquals(true, allergies.isAllergicTo(Allergen.PEANUTS))
32
- }
33
-
34
- @Ignore
35
- @Test
36
- fun allergicToShellfish() {
37
- val allergies = Allergies(4)
38
-
39
- assertEquals(true, allergies.isAllergicTo(Allergen.SHELLFISH))
40
- }
41
-
42
- @Ignore
43
- @Test
44
- fun allergicToStrawberries() {
45
- val allergies = Allergies(8)
46
-
47
- assertEquals(true, allergies.isAllergicTo(Allergen.STRAWBERRIES))
23
+ assertTrue(allergies.isAllergicTo(Allergen.EGGS))
48
24
  }
49
25
 
50
26
  @Ignore
51
27
  @Test
52
- fun allergicToTomatoes() {
53
- val allergies = Allergies(16)
54
-
55
- assertEquals(true, allergies.isAllergicTo(Allergen.TOMATOES))
56
- }
57
-
58
- @Ignore
59
- @Test
60
- fun allergicToChocolate() {
61
- val allergies = Allergies(32)
62
-
63
- assertEquals(true, allergies.isAllergicTo(Allergen.CHOCOLATE))
64
- }
65
-
66
- @Ignore
67
- @Test
68
- fun allergicToPollen() {
69
- val allergies = Allergies(64)
70
-
71
- assertEquals(true, allergies.isAllergicTo(Allergen.POLLEN))
72
- }
73
-
74
- @Ignore
75
- @Test
76
- fun allergicToCats() {
77
- val allergies = Allergies(128)
78
-
79
- assertEquals(true, allergies.isAllergicTo(Allergen.CATS))
80
- }
81
-
82
- @Ignore
83
- @Test
84
- fun isAllergicToEggsInAdditionToOtherStuff() {
28
+ fun allergicToEggsAndOtherThings() {
85
29
  val allergies = Allergies(5)
86
30
 
87
- assertEquals(true, allergies.isAllergicTo(Allergen.EGGS))
31
+ assertTrue(allergies.isAllergicTo(Allergen.EGGS))
32
+ assertTrue(allergies.isAllergicTo(Allergen.SHELLFISH))
33
+ assertFalse(allergies.isAllergicTo(Allergen.STRAWBERRIES))
88
34
  }
89
35
 
90
36
  @Ignore
@@ -92,12 +38,12 @@ class AllergiesTest {
92
38
  fun noAllergies() {
93
39
  val allergies = Allergies(0)
94
40
 
95
- assertEquals(0, allergies.getList().size)
41
+ assertTrue(allergies.getList().isEmpty())
96
42
  }
97
43
 
98
44
  @Ignore
99
45
  @Test
100
- fun isAllergicToJustEggs() {
46
+ fun allergicToJustEggs() {
101
47
  val allergies = Allergies(1)
102
48
  val expectedAllergens = listOf(Allergen.EGGS)
103
49
 
@@ -106,7 +52,7 @@ class AllergiesTest {
106
52
 
107
53
  @Ignore
108
54
  @Test
109
- fun isAllergicToJustPeanuts() {
55
+ fun allergicToJustPeanuts() {
110
56
  val allergies = Allergies(2)
111
57
  val expectedAllergens = listOf(Allergen.PEANUTS)
112
58
 
@@ -115,7 +61,7 @@ class AllergiesTest {
115
61
 
116
62
  @Ignore
117
63
  @Test
118
- fun isAllergicToJustStrawberries() {
64
+ fun allergicToJustStrawberries() {
119
65
  val allergies = Allergies(8)
120
66
  val expectedAllergens = listOf(Allergen.STRAWBERRIES)
121
67
 
@@ -124,7 +70,7 @@ class AllergiesTest {
124
70
 
125
71
  @Ignore
126
72
  @Test
127
- fun isAllergicToEggsAndPeanuts() {
73
+ fun allergicToEggsAndPeanuts() {
128
74
  val allergies = Allergies(3)
129
75
  val expectedAllergens = listOf(
130
76
  Allergen.EGGS,
@@ -136,7 +82,7 @@ class AllergiesTest {
136
82
 
137
83
  @Ignore
138
84
  @Test
139
- fun isAllergicToEggsAndShellfish() {
85
+ fun allergicToEggsAndShellfish() {
140
86
  val allergies = Allergies(5)
141
87
  val expectedAllergens = listOf(
142
88
  Allergen.EGGS,
@@ -148,7 +94,7 @@ class AllergiesTest {
148
94
 
149
95
  @Ignore
150
96
  @Test
151
- fun isAllergicToLotsOfStuff() {
97
+ fun allergicToLotsOfStuff() {
152
98
  val allergies = Allergies(248)
153
99
  val expectedAllergens = listOf(
154
100
  Allergen.STRAWBERRIES,
@@ -163,7 +109,7 @@ class AllergiesTest {
163
109
 
164
110
  @Ignore
165
111
  @Test
166
- fun isAllergicToEverything() {
112
+ fun allergicToEverything() {
167
113
  val allergies = Allergies(255)
168
114
  val expectedAllergens = listOf(
169
115
  Allergen.EGGS,
@@ -195,4 +141,5 @@ class AllergiesTest {
195
141
 
196
142
  assertEquals(expectedAllergens, allergies.getList())
197
143
  }
144
+
198
145
  }
@@ -1,8 +1,11 @@
1
- class Anagram(val word: String) {
1
+ class Anagram(private val word: String) {
2
+
2
3
  fun match(anagrams: Collection<String>) =
3
- anagrams.filter({ doesMatch(it) }).filterNot({ it.equals(word, ignoreCase = true) })
4
+ anagrams.filter { containSameChars(it.toLowerCase()) }
5
+ .filterNot { it.equals(word, ignoreCase = true) }
6
+ .toSet()
4
7
 
5
- private fun doesMatch(anagram: String) =
6
- anagram.toLowerCase().toCharArray().sorted() == word.toLowerCase().toCharArray().sorted()
8
+ private fun containSameChars(candidate: String) =
9
+ candidate.toLowerCase().toCharArray().sorted() == word.toLowerCase().toCharArray().sorted()
7
10
 
8
11
  }
@@ -4,81 +4,128 @@ import kotlin.test.assertEquals
4
4
 
5
5
  class AnagramTest {
6
6
 
7
-
8
7
  @Test
9
8
  fun noMatches() {
10
9
  val detector = Anagram("diaper")
11
- assertEquals(listOf(), detector.match(listOf("hello", "world", "zombies", "pants")))
10
+ assertEquals(emptySet(), detector.match(listOf("hello", "world", "zombies", "pants")))
12
11
  }
13
12
 
14
13
  @Ignore
15
14
  @Test
16
- fun simpleAnagram() {
15
+ fun detectsSimpleAnagram() {
17
16
  val detector = Anagram("ant")
18
17
  val anagram = detector.match(listOf("tan", "stand", "at"))
19
- assertEquals(listOf("tan"), anagram)
18
+ assertEquals(setOf("tan"), anagram)
19
+ }
20
+
21
+ @Ignore
22
+ @Test
23
+ fun doesNotDetectFalsePositives() {
24
+ val detector = Anagram("galea")
25
+ val anagrams = detector.match(listOf("eagle"))
26
+ assertEquals(emptySet(), anagrams)
20
27
  }
21
28
 
22
29
  @Ignore
23
30
  @Test
24
- fun detectMultipleAnagrams() {
31
+ fun detectsTwoAnagrams() {
25
32
  val detector = Anagram("master")
26
33
  val anagrams = detector.match(listOf("stream", "pigeon", "maters"))
27
- assertEquals(listOf("maters", "stream"), anagrams.sorted())
34
+ assertEquals(setOf("maters", "stream"), anagrams)
28
35
  }
29
36
 
30
37
  @Ignore
31
38
  @Test
32
- fun doesNotConfuseDifferentDuplicates() {
33
- val detector = Anagram("galea")
34
- val anagrams = detector.match(listOf("eagle"))
35
- assertEquals(listOf(), anagrams)
39
+ fun doesNotDetectAnagramSubsets() {
40
+ val detector = Anagram("good")
41
+ assertEquals(emptySet(), detector.match(listOf("dog", "goody")))
36
42
  }
37
43
 
38
44
  @Ignore
39
45
  @Test
40
- fun identicalWordIsNotAnagram() {
46
+ fun detectsLongerAnagram() {
47
+ val detector = Anagram("listen")
48
+ val anagrams = detector.match(listOf("enlists", "google", "inlets", "banana"))
49
+ assertEquals(setOf("inlets"), anagrams)
50
+ }
51
+
52
+ @Ignore
53
+ @Test
54
+ fun detectsThreeAnagrams() {
55
+ val detector = Anagram("allergy")
56
+ val anagrams = detector.match(listOf("gallery", "ballerina", "regally", "clergy", "largely", "leading"))
57
+ assertEquals(setOf("gallery", "largely", "regally"), anagrams)
58
+ }
59
+
60
+ @Ignore
61
+ @Test
62
+ fun doesNotDetectIdenticalWordAsAnagram() {
41
63
  val detector = Anagram("corn")
42
64
  val anagrams = detector.match(listOf("corn", "dark", "Corn", "rank", "CORN", "cron", "park"))
43
- assertEquals(listOf("cron"), anagrams)
65
+ assertEquals(setOf("cron"), anagrams)
44
66
  }
45
67
 
46
68
  @Ignore
47
69
  @Test
48
- fun eliminateAnagramsWithSameChecksum() {
70
+ fun doesNotDetectNonAnagramsWithIdenticalChecksums() {
49
71
  val detector = Anagram("mass")
50
- assertEquals(listOf(), detector.match(listOf("last")))
72
+ assertEquals(emptySet(), detector.match(listOf("last")))
51
73
  }
52
74
 
53
75
  @Ignore
54
76
  @Test
55
- fun eliminateAnagramSubsets() {
56
- val detector = Anagram("good")
57
- assertEquals(listOf(), detector.match(listOf("dog", "goody")))
77
+ fun detectsAnagramsCaseInsensitively() {
78
+ val detector = Anagram("Orchestra")
79
+ val anagrams = detector.match(listOf("cashregister", "Carthorse", "radishes"))
80
+ assertEquals(setOf("Carthorse"), anagrams)
58
81
  }
59
82
 
60
83
  @Ignore
61
84
  @Test
62
- fun detectAnagrams() {
63
- val detector = Anagram("listen")
64
- val anagrams = detector.match(listOf("enlists", "google", "inlets", "banana"))
65
- assertEquals(listOf("inlets"), anagrams)
85
+ fun detectsAnagramsUsingCaseInsensitiveSubject() {
86
+ val detector = Anagram("Orchestra")
87
+ val anagrams = detector.match(listOf("cashregister", "carthorse", "radishes"))
88
+ assertEquals(setOf("carthorse"), anagrams)
66
89
  }
67
90
 
68
91
  @Ignore
69
92
  @Test
70
- fun multipleAnagrams() {
71
- val detector = Anagram("allergy")
72
- val anagrams = detector.match(listOf("gallery", "ballerina", "regally", "clergy", "largely", "leading"))
73
- assertEquals(listOf("gallery", "largely", "regally"), anagrams.sorted())
93
+ fun detectsAnagramsUsingCaseInsensitiveCandidates() {
94
+ val detector = Anagram("orchestra")
95
+ val anagrams = detector.match(listOf("cashregister", "Carthorse", "radishes"))
96
+ assertEquals(setOf("Carthorse"), anagrams)
74
97
  }
75
98
 
76
99
  @Ignore
77
100
  @Test
78
- fun anagramsAreCaseInsensitive() {
79
- val detector = Anagram("Orchestra")
80
- val anagrams = detector.match(listOf("cashregister", "Carthorse", "radishes"))
81
- assertEquals(listOf("Carthorse"), anagrams)
101
+ fun doesNotDetectIdenticalWordWithMixedCasingAsAnagram() {
102
+ val detector = Anagram("banana")
103
+ val anagrams = detector.match(listOf("Banana"))
104
+ assertEquals(emptySet(), anagrams)
105
+ }
106
+
107
+ @Ignore
108
+ @Test
109
+ fun doesNotDetectAnAnagramIfTheOriginalWordIsRepeated() {
110
+ val detector = Anagram("go")
111
+ val anagrams = detector.match(listOf("go Go GO"))
112
+ assertEquals(emptySet(), anagrams)
113
+ }
114
+
115
+ @Ignore
116
+ @Test
117
+ fun anagramsMustUseAllLettersExactlyOnce() {
118
+ val detector = Anagram("tapper")
119
+ val anagrams = detector.match(listOf("patter"))
120
+ assertEquals(emptySet(), anagrams)
121
+ }
122
+
123
+ @Ignore
124
+ @Test
125
+ fun doesNotDetectIdenticalUppercasedWordAsAnagram() {
126
+ val detector = Anagram("BANANA")
127
+ val anagrams = detector.match(listOf("Banana"))
128
+ assertEquals(emptySet(), anagrams)
82
129
  }
83
130
 
84
131
  }