trackler 2.0.8.42 → 2.0.8.43

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/bracket-push/canonical-data.json +7 -1
  3. data/lib/trackler/version.rb +1 -1
  4. data/tracks/c/exercises/react/src/example.c +106 -34
  5. data/tracks/csharp/exercises/zipper/HINTS.md +2 -0
  6. data/tracks/delphi/.github/stale.yml +1 -0
  7. data/tracks/go/exercises/bank-account/bank_account_test.go +1 -1
  8. data/tracks/go/exercises/variable-length-quantity/example.go +3 -3
  9. data/tracks/go/exercises/variable-length-quantity/variable_length_quantity_test.go +11 -11
  10. data/tracks/haskell/config.json +21 -1
  11. data/tracks/haskell/exercises/acronym/examples/success-standard/package.yaml +16 -0
  12. data/tracks/haskell/exercises/acronym/examples/success-standard/src/Acronym.hs +21 -0
  13. data/tracks/haskell/exercises/acronym/package.yaml +19 -0
  14. data/tracks/haskell/exercises/acronym/src/Acronym.hs +4 -0
  15. data/tracks/haskell/exercises/acronym/stack.yaml +1 -0
  16. data/tracks/haskell/exercises/acronym/test/Tests.hs +57 -0
  17. data/tracks/haskell/exercises/bracket-push/examples/success-standard/package.yaml +16 -0
  18. data/tracks/haskell/exercises/bracket-push/examples/success-standard/src/Brackets.hs +36 -0
  19. data/tracks/haskell/exercises/bracket-push/package.yaml +19 -0
  20. data/tracks/haskell/exercises/bracket-push/src/Brackets.hs +4 -0
  21. data/tracks/haskell/exercises/bracket-push/stack.yaml +1 -0
  22. data/tracks/haskell/exercises/bracket-push/test/Tests.hs +85 -0
  23. data/tracks/haskell/exercises/pangram/examples/success-standard/package.yaml +16 -0
  24. data/tracks/haskell/exercises/pangram/examples/success-standard/src/Pangram.hs +7 -0
  25. data/tracks/haskell/exercises/pangram/package.yaml +19 -0
  26. data/tracks/haskell/exercises/pangram/src/Pangram.hs +4 -0
  27. data/tracks/haskell/exercises/pangram/stack.yaml +1 -0
  28. data/tracks/haskell/exercises/pangram/test/Tests.hs +65 -0
  29. data/tracks/java/exercises/flatten-array/src/test/java/FlattenerTest.java +15 -0
  30. data/tracks/java/exercises/pig-latin/src/example/java/{PigLatin.java → PigLatinTranslator.java} +8 -8
  31. data/tracks/java/exercises/pig-latin/src/test/java/{PigLatinTest.java → PigLatinTranslatorTest.java} +4 -5
  32. data/tracks/java/exercises/prime-factors/src/example/java/{PrimeFactors.java → PrimeFactorsCalculator.java} +2 -2
  33. data/tracks/java/exercises/prime-factors/src/test/java/{PrimeFactorsTest.java → PrimeFactorsCalculatorTest.java} +8 -8
  34. data/tracks/python/exercises/allergies/allergies_test.py +38 -8
  35. data/tracks/python/exercises/pig-latin/pig_latin_test.py +27 -10
  36. data/tracks/ruby/.github/stale.yml +0 -0
  37. metadata +27 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad0c8c481adab8fc6597c91e49a145230f5a0e3d
4
- data.tar.gz: bf9269a54e783bf01145d450c8712d57eb0d8204
3
+ metadata.gz: a9834bb8d7cd54e4b2c8e1e26da6932cf1e95cc5
4
+ data.tar.gz: 21645918c226fde411b8ae99233e4fcd3abe2e97
5
5
  SHA512:
6
- metadata.gz: dc3576e5ff9be012b404eafa0776795a2aaf6bd09903bf9cf4f42554b9da8cddb6974c92714b867c232cd8476da1fc504de6e90510d59ccca087bf9ab5329a94
7
- data.tar.gz: 25537ab8bb99975a7bb6507c4e9153f722912f6d970c2b64481e75fcc9dd61e1456e7517be2b85226242c1b66cb220f3332b8f298626f4188c7728b82b81dcc1
6
+ metadata.gz: 929126636d31a8a2c0d54e607e5b64c2b131087594b836796e2a9f282dde25d522af1a0174bde3ee6939fc4679b0107dbad40e6982e517636124cd9743dff7f9
7
+ data.tar.gz: 484e966fda60ece17a4553d9b82e4a5974f2b763acd58369283b5a2f2f3197d931d6e34f4449e41e175c1bb34be8f63d17b574b7d0c65c60048d59e1e4b322c5
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "exercise": "bracket-push",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "cases": [
5
5
  {
6
6
  "description": "paired square brackets",
@@ -26,6 +26,12 @@
26
26
  "input": "}{",
27
27
  "expected": false
28
28
  },
29
+ {
30
+ "description": "wrong closing bracket",
31
+ "property": "isPaired",
32
+ "input": "{]",
33
+ "expected": false
34
+ },
29
35
  {
30
36
  "description": "paired with whitespace",
31
37
  "property": "isPaired",
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.8.42"
2
+ VERSION = "2.0.8.43"
3
3
  end
@@ -20,18 +20,20 @@ struct cb {
20
20
  };
21
21
 
22
22
  struct reactor {
23
- struct child *first;
24
- struct child *last;
23
+ struct child *input;
25
24
  };
26
25
 
27
26
  struct cell {
28
- struct reactor *reactor;
29
27
  int value;
30
28
  enum cell_kind kind;
29
+ struct child *child;
30
+
31
31
  struct cell *input1;
32
32
  struct cell *input2;
33
33
  compute1 compute1;
34
34
  compute2 compute2;
35
+
36
+ int last_cb_value;
35
37
  struct cb *cb;
36
38
  int callbacks_issued;
37
39
  };
@@ -41,42 +43,74 @@ struct reactor *create_reactor()
41
43
  return calloc(1, sizeof(struct reactor));
42
44
  }
43
45
 
44
- void destroy_reactor(struct reactor *r)
46
+ static void destroy_cell(struct cell *c)
45
47
  {
46
- struct child *child = r->first;
47
- while (child) {
48
- struct cb *cb = child->cell->cb;
49
- while (cb) {
50
- struct cb *next_cb = cb->next;
51
- free(cb);
52
- cb = next_cb;
53
- }
54
- free(child->cell);
48
+ struct cb *cb = c->cb;
49
+ while (cb) {
50
+ struct cb *next_cb = cb->next;
51
+ free(cb);
52
+ cb = next_cb;
53
+ }
55
54
 
55
+ struct child *child = c->child;
56
+ while (child) {
56
57
  struct child *next = child->next;
58
+ if (c == child->cell->input1) {
59
+ // Don't double-free for a compute2 cell.
60
+ destroy_cell(child->cell);
61
+ }
57
62
  free(child);
58
63
  child = next;
59
64
  }
65
+
66
+ free(c);
67
+ }
68
+
69
+ void destroy_reactor(struct reactor *r)
70
+ {
71
+ struct child *input = r->input;
72
+ while (input) {
73
+ struct child *next = input->next;
74
+ destroy_cell(input->cell);
75
+ free(input);
76
+ input = next;
77
+ }
78
+
60
79
  free(r);
61
80
  }
62
81
 
63
- static void add_child(struct reactor *r, struct cell *cell)
82
+ #define SUCCESS 1
83
+ #define FAIL 0
84
+
85
+ static int add_child(struct child **list, struct cell *cell)
64
86
  {
65
87
  struct child *child = calloc(1, sizeof(struct child));
66
- child->cell = cell;
67
- if (!r->first) {
68
- r->first = child;
69
- } else {
70
- r->last->next = child;
88
+ if (!child) {
89
+ return FAIL;
71
90
  }
72
- r->last = child;
91
+ child->cell = cell;
92
+ child->next = *list;
93
+ *list = child;
94
+ return SUCCESS;
95
+ }
96
+
97
+ static void remove_child(struct child **list)
98
+ {
99
+ struct child *to_remove = *list;
100
+ *list = to_remove->next;
101
+ free(to_remove);
73
102
  }
74
103
 
75
104
  struct cell *create_input_cell(struct reactor *r, int initial_value)
76
105
  {
77
106
  struct cell *c = calloc(1, sizeof(struct cell));
78
- add_child(r, c);
79
- c->reactor = r;
107
+ if (!c) {
108
+ return NULL;
109
+ }
110
+ if (add_child(&r->input, c) != SUCCESS) {
111
+ free(c);
112
+ return NULL;
113
+ }
80
114
  c->kind = kind_input;
81
115
  c->value = initial_value;
82
116
  return c;
@@ -85,30 +119,51 @@ struct cell *create_input_cell(struct reactor *r, int initial_value)
85
119
  struct cell *create_compute1_cell(struct reactor *r, struct cell *input,
86
120
  compute1 compute)
87
121
  {
122
+ (void)r;
88
123
  struct cell *c = calloc(1, sizeof(struct cell));
89
- add_child(r, c);
90
- c->reactor = r;
124
+ if (!c) {
125
+ return NULL;
126
+ }
127
+ if (add_child(&input->child, c) != SUCCESS) {
128
+ free(c);
129
+ return NULL;
130
+ }
91
131
  c->kind = kind_compute1;
92
132
  c->input1 = input;
93
133
  c->compute1 = compute;
94
134
  c->value = compute(get_cell_value(input));
135
+ c->last_cb_value = c->value;
95
136
  return c;
96
137
  }
97
138
 
98
139
  struct cell *create_compute2_cell(struct reactor *r, struct cell *input1,
99
140
  struct cell *input2, compute2 compute)
100
141
  {
142
+ (void)r;
101
143
  struct cell *c = calloc(1, sizeof(struct cell));
102
- add_child(r, c);
103
- c->reactor = r;
144
+ if (!c) {
145
+ return NULL;
146
+ }
147
+ if (add_child(&input1->child, c) != SUCCESS) {
148
+ free(c);
149
+ return NULL;
150
+ }
151
+ if (add_child(&input2->child, c) != SUCCESS) {
152
+ remove_child(&input1->child);
153
+ free(c);
154
+ return NULL;
155
+ }
104
156
  c->kind = kind_compute2;
105
157
  c->input1 = input1;
106
158
  c->input2 = input2;
107
159
  c->compute2 = compute;
108
160
  c->value = compute(get_cell_value(input1), get_cell_value(input2));
161
+ c->last_cb_value = c->value;
109
162
  return c;
110
163
  }
111
164
 
165
+ #define each_child(c) struct child *child = (c)->child; child; child = child->next
166
+
112
167
  int get_cell_value(struct cell *c)
113
168
  {
114
169
  return c->value;
@@ -131,29 +186,46 @@ static void propagate(struct cell *c)
131
186
 
132
187
  if (new_value != c->value) {
133
188
  c->value = new_value;
134
- for (struct cb * cb = c->cb; cb; cb = cb->next) {
135
- cb->f(cb->obj, new_value);
189
+ for (each_child(c)) {
190
+ propagate(child->cell);
136
191
  }
137
192
  }
193
+ }
138
194
 
195
+ static void fire_callbacks(struct cell *c)
196
+ {
197
+ if (c->value == c->last_cb_value) {
198
+ return;
199
+ }
200
+ c->last_cb_value = c->value;
201
+ for (struct cb * cb = c->cb; cb; cb = cb->next) {
202
+ cb->f(cb->obj, c->value);
203
+ }
204
+ for (each_child(c)) {
205
+ fire_callbacks(child->cell);
206
+ }
139
207
  }
140
208
 
141
209
  void set_cell_value(struct cell *c, int new_value)
142
210
  {
143
211
  c->value = new_value;
144
- struct reactor *r = c->reactor;
145
-
146
- // We take the very naive route of updating all cells.
147
- // Traversing the tree and only updating the cells dependent on the just-changed cell is possible,
148
- // but requires much more memory management to make each cell aware of its dependents.
149
- for (struct child * child = r->first; child; child = child->next) {
212
+ for (each_child(c)) {
150
213
  propagate(child->cell);
151
214
  }
215
+ for (each_child(c)) {
216
+ // Why can't we put propagate and fire_callbacks in same for loop?
217
+ // Because then a compute2 cell might fire its callbacks too early
218
+ // (before it's seen updates from both of its inputs)!
219
+ fire_callbacks(child->cell);
220
+ }
152
221
  }
153
222
 
154
223
  callback_id add_callback(struct cell *c, void *obj, callback f)
155
224
  {
156
225
  struct cb *cb = calloc(1, sizeof(struct cb));
226
+ if (!cb) {
227
+ return -1;
228
+ }
157
229
  cb->id = c->callbacks_issued++;
158
230
  cb->next = c->cb;
159
231
  cb->obj = obj;
@@ -0,0 +1,2 @@
1
+ ## Hints
2
+ This exercise deals with custom equality. For more information see [this page.](http://www.loganfranken.com/blog/687/overriding-equals-in-c-part-1/)
@@ -0,0 +1 @@
1
+
@@ -1,6 +1,6 @@
1
1
  // API:
2
2
  //
3
- // Open(initalDeposit int64) *Account
3
+ // Open(initialDeposit int64) *Account
4
4
  // (Account) Close() (payout int64, ok bool)
5
5
  // (Account) Balance() (balance int64, ok bool)
6
6
  // (Account) Deposit(amount int64) (newBalance int64, ok bool)
@@ -1,6 +1,6 @@
1
1
  package variablelengthquantity
2
2
 
3
- const testVersion = 1
3
+ const testVersion = 2
4
4
 
5
5
  // EncodeVarint returns the varint encoding of x.
6
6
  func EncodeVarint(x uint32) []byte {
@@ -50,9 +50,9 @@ func DecodeVarint(buf []byte) (x uint32, n int) {
50
50
  x = x << 7
51
51
  x |= uint32(b) & 0x7F
52
52
  if (b & 0x80) == 0 {
53
- return x, n
53
+ return x, n + 1
54
54
  }
55
55
  }
56
56
 
57
- return x, n
57
+ return x, 0
58
58
  }
@@ -5,7 +5,7 @@ import (
5
5
  "testing"
6
6
  )
7
7
 
8
- const targetTestVersion = 1
8
+ const targetTestVersion = 2
9
9
 
10
10
  var testCases = []struct {
11
11
  input []byte
@@ -13,16 +13,16 @@ var testCases = []struct {
13
13
  size int
14
14
  }{
15
15
  0: {[]byte{0x7F}, 127, 1},
16
- 1: {[]byte{0x81, 0x00}, 128, 1},
17
- 2: {[]byte{0xC0, 0x00}, 8192, 1},
18
- 3: {[]byte{0xFF, 0x7F}, 16383, 1},
19
- 4: {[]byte{0x81, 0x80, 0x00}, 16384, 2},
20
- 5: {[]byte{0xFF, 0xFF, 0x7F}, 2097151, 2},
21
- 6: {[]byte{0x81, 0x80, 0x80, 0x00}, 2097152, 3},
22
- 7: {[]byte{0xC0, 0x80, 0x80, 0x00}, 134217728, 3},
23
- 8: {[]byte{0xFF, 0xFF, 0xFF, 0x7F}, 268435455, 3},
24
- 9: {[]byte{0x82, 0x00}, 256, 1},
25
- 10: {[]byte{0x81, 0x10}, 144, 1},
16
+ 1: {[]byte{0x81, 0x00}, 128, 2},
17
+ 2: {[]byte{0xC0, 0x00}, 8192, 2},
18
+ 3: {[]byte{0xFF, 0x7F}, 16383, 2},
19
+ 4: {[]byte{0x81, 0x80, 0x00}, 16384, 3},
20
+ 5: {[]byte{0xFF, 0xFF, 0x7F}, 2097151, 3},
21
+ 6: {[]byte{0x81, 0x80, 0x80, 0x00}, 2097152, 4},
22
+ 7: {[]byte{0xC0, 0x80, 0x80, 0x00}, 134217728, 4},
23
+ 8: {[]byte{0xFF, 0xFF, 0xFF, 0x7F}, 268435455, 4},
24
+ 9: {[]byte{0x82, 0x00}, 256, 2},
25
+ 10: {[]byte{0x81, 0x10}, 144, 2},
26
26
  }
27
27
 
28
28
  func TestTestVersion(t *testing.T) {
@@ -28,6 +28,12 @@
28
28
  "topics": [
29
29
  ]
30
30
  },
31
+ {
32
+ "slug": "pangram",
33
+ "difficulty": 1,
34
+ "topics": [
35
+ ]
36
+ },
31
37
  {
32
38
  "slug": "run-length-encoding",
33
39
  "difficulty": 1,
@@ -60,6 +66,12 @@
60
66
  "Maybe"
61
67
  ]
62
68
  },
69
+ {
70
+ "slug": "acronym",
71
+ "difficulty": 2,
72
+ "topics": [
73
+ ]
74
+ },
63
75
  {
64
76
  "slug": "hamming",
65
77
  "difficulty": 2,
@@ -273,6 +285,13 @@
273
285
  "topics": [
274
286
  ]
275
287
  },
288
+ {
289
+ "slug": "bracket-push",
290
+ "difficulty": 5,
291
+ "topics": [
292
+ "Stack"
293
+ ]
294
+ },
276
295
  {
277
296
  "slug": "crypto-square",
278
297
  "difficulty": 5,
@@ -491,7 +510,8 @@
491
510
  "difficulty": 10,
492
511
  "topics": [
493
512
  "Define type",
494
- "Either"
513
+ "Either",
514
+ "Stack"
495
515
  ]
496
516
  },
497
517
  {
@@ -0,0 +1,16 @@
1
+ name: acronym
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Acronym
8
+ source-dirs: src
9
+
10
+ tests:
11
+ test:
12
+ main: Tests.hs
13
+ source-dirs: test
14
+ dependencies:
15
+ - acronym
16
+ - hspec
@@ -0,0 +1,21 @@
1
+ module Acronym (abbreviate) where
2
+
3
+ import Data.Char (isAlpha, isUpper, toUpper)
4
+
5
+ abbreviate :: String -> String
6
+ abbreviate = concatMap initials . words . map replaceNonAlpha
7
+
8
+ initials :: String -> String
9
+ initials [] = []
10
+ initials (x:xs) = toUpper x : rest
11
+ where rest = if not $ isAcronym xs
12
+ then filter isUpper xs
13
+ else []
14
+
15
+ isAcronym :: String -> Bool
16
+ isAcronym = all isUpper
17
+
18
+ replaceNonAlpha :: Char -> Char
19
+ replaceNonAlpha x
20
+ | isAlpha x = x
21
+ | otherwise = ' '
@@ -0,0 +1,19 @@
1
+ name: acronym
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Acronym
8
+ source-dirs: src
9
+ dependencies:
10
+ # - foo # List here the packages you
11
+ # - bar # want to use in your solution.
12
+
13
+ tests:
14
+ test:
15
+ main: Tests.hs
16
+ source-dirs: test
17
+ dependencies:
18
+ - acronym
19
+ - hspec
@@ -0,0 +1,4 @@
1
+ module Acronym (abbreviate) where
2
+
3
+ abbreviate :: String -> String
4
+ abbreviate xs = error "You need to implement this function."
@@ -0,0 +1 @@
1
+ resolver: lts-8.2
@@ -0,0 +1,57 @@
1
+ {-# LANGUAGE RecordWildCards #-}
2
+
3
+ import Data.Foldable (for_)
4
+ import Test.Hspec (Spec, describe, it, shouldBe)
5
+ import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
6
+
7
+ import Acronym (abbreviate)
8
+
9
+ main :: IO ()
10
+ main = hspecWith defaultConfig {configFastFail = True} specs
11
+
12
+ specs :: Spec
13
+ specs = describe "acronym" $
14
+ describe "abbreviate" $ for_ cases test
15
+ where
16
+ test Case {..} = it description $ abbreviate input `shouldBe` expected
17
+
18
+ -- Adapted from
19
+ -- Source: exercism/x-common/exercises/acronym/canonical-data.json
20
+ -- Version: 1.0.0
21
+ -- Date: 2017-03-31
22
+
23
+ data Case = Case { description :: String
24
+ , input :: String
25
+ , expected :: String
26
+ }
27
+
28
+ cases :: [Case]
29
+ cases = [ Case { description = "basic"
30
+ , input = "Portable Network Graphics"
31
+ , expected = "PNG"
32
+ }
33
+ , Case { description = "lowercase words"
34
+ , input = "Ruby on Rails"
35
+ , expected = "ROR"
36
+ }
37
+ , Case { description = "camelcase"
38
+ , input = "HyperText Markup Language"
39
+ , expected = "HTML"
40
+ }
41
+ , Case { description = "punctuation"
42
+ , input = "First In, First Out"
43
+ , expected = "FIFO"
44
+ }
45
+ , Case { description = "all caps words"
46
+ , input = "PHP: Hypertext Preprocessor"
47
+ , expected = "PHP"
48
+ }
49
+ , Case { description = "non-acronym all caps word"
50
+ , input = "GNU Image Manipulation Program"
51
+ , expected = "GIMP"
52
+ }
53
+ , Case { description = "hyphenated"
54
+ , input = "Complementary metal-oxide semiconductor"
55
+ , expected = "CMOS"
56
+ }
57
+ ]
@@ -0,0 +1,16 @@
1
+ name: bracket-push
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Brackets
8
+ source-dirs: src
9
+
10
+ tests:
11
+ test:
12
+ main: Tests.hs
13
+ source-dirs: test
14
+ dependencies:
15
+ - bracket-push
16
+ - hspec
@@ -0,0 +1,36 @@
1
+ module Brackets (arePaired) where
2
+
3
+ data BracketType = Opening | Closing
4
+ data Stack a = Empty | Elem a (Stack a)
5
+
6
+ push :: Char -> Stack Char -> Stack Char
7
+ push = Elem
8
+
9
+ pop :: Stack Char -> Stack Char
10
+ pop Empty = Empty
11
+ pop (Elem _ stack) = stack
12
+
13
+ arePaired :: String -> Bool
14
+ arePaired xs = checkBalance xs Empty
15
+
16
+ checkBalance :: String -> Stack Char -> Bool
17
+ checkBalance [] Empty = True
18
+ checkBalance [] _ = False
19
+ checkBalance (x:xs) stack =
20
+ case classify x of
21
+ Just Opening -> checkBalance xs $ push x stack
22
+ Just Closing -> (x `closes` stack) && checkBalance xs (pop stack)
23
+ _ -> checkBalance xs stack
24
+
25
+ classify :: Char -> Maybe BracketType
26
+ classify x
27
+ | x `elem` "([{" = Just Opening
28
+ | x `elem` ")]}" = Just Closing
29
+ | otherwise = Nothing
30
+
31
+ closes :: Char -> Stack Char -> Bool
32
+ closes _ Empty = False
33
+ closes x (Elem y _) =
34
+ x == ')' && y == '('
35
+ || x == ']' && y == '['
36
+ || x == '}' && y == '{'
@@ -0,0 +1,19 @@
1
+ name: bracket-push
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Brackets
8
+ source-dirs: src
9
+ dependencies:
10
+ # - foo # List here the packages you
11
+ # - bar # want to use in your solution.
12
+
13
+ tests:
14
+ test:
15
+ main: Tests.hs
16
+ source-dirs: test
17
+ dependencies:
18
+ - bracket-push
19
+ - hspec
@@ -0,0 +1,4 @@
1
+ module Brackets (arePaired) where
2
+
3
+ arePaired :: String -> Bool
4
+ arePaired xs = error "You need to implement this function."
@@ -0,0 +1 @@
1
+ resolver: lts-8.2
@@ -0,0 +1,85 @@
1
+ {-# LANGUAGE RecordWildCards #-}
2
+
3
+ import Data.Foldable (for_)
4
+ import Test.Hspec (Spec, describe, it, shouldBe)
5
+ import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
6
+
7
+ import Brackets (arePaired)
8
+
9
+ main :: IO ()
10
+ main = hspecWith defaultConfig {configFastFail = True} specs
11
+
12
+ specs :: Spec
13
+ specs = describe "bracket-push" $
14
+ describe "isPaired" $ for_ cases test
15
+ where
16
+ test Case{..} = it description $ arePaired input `shouldBe` expected
17
+
18
+ -- Adapted from
19
+ -- Source: exercism/x-common/exercises/bracket-push/canonical-data.json
20
+ -- Version: 1.1.0
21
+ -- Date: 2017-04-07.
22
+
23
+ data Case = Case { description :: String
24
+ , input :: String
25
+ , expected :: Bool
26
+ }
27
+
28
+ cases :: [Case]
29
+ cases = [ Case { description = "paired square brackets"
30
+ , input = "[]"
31
+ , expected = True
32
+ }
33
+ , Case { description = "empty string"
34
+ , input = ""
35
+ , expected = True
36
+ }
37
+ , Case { description = "unpaired brackets"
38
+ , input = "[["
39
+ , expected = False
40
+ }
41
+ , Case { description = "wrong ordered brackets"
42
+ , input = "}{"
43
+ , expected = False
44
+ }
45
+ , Case { description = "wrong closing brackets"
46
+ , input = "{]"
47
+ , expected = False
48
+ }
49
+ , Case { description = "paired with whitespace"
50
+ , input = "{ }"
51
+ , expected = True
52
+ }
53
+ , Case { description = "simple nested brackets"
54
+ , input = "{[]}"
55
+ , expected = True
56
+ }
57
+ , Case { description = "several paired brackets"
58
+ , input = "{}[]"
59
+ , expected = True
60
+ }
61
+ , Case { description = "paired and nested brackets"
62
+ , input = "([{}({}[])])"
63
+ , expected = True
64
+ }
65
+ , Case { description = "unopened closing brackets"
66
+ , input = "{[)][]}"
67
+ , expected = False
68
+ }
69
+ , Case { description = "unpaired and nested brackets"
70
+ , input = "([{])"
71
+ , expected = False
72
+ }
73
+ , Case { description = "paired and wrong nested brackets"
74
+ , input = "[({]})"
75
+ , expected = False
76
+ }
77
+ , Case { description = "math expression"
78
+ , input = "(((185 + 223.85) * 15) - 543)/2"
79
+ , expected = True
80
+ }
81
+ , Case { description = "complex latex expression"
82
+ , input = "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)"
83
+ , expected = True
84
+ }
85
+ ]
@@ -0,0 +1,16 @@
1
+ name: pangram
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Pangram
8
+ source-dirs: src
9
+
10
+ tests:
11
+ test:
12
+ main: Tests.hs
13
+ source-dirs: test
14
+ dependencies:
15
+ - pangram
16
+ - hspec
@@ -0,0 +1,7 @@
1
+ module Pangram (isPangram) where
2
+
3
+ import Data.Char (toLower)
4
+
5
+ isPangram :: String -> Bool
6
+ isPangram xs = all (`elem` fixedText) ['a'..'z']
7
+ where fixedText = map toLower xs
@@ -0,0 +1,19 @@
1
+ name: pangram
2
+
3
+ dependencies:
4
+ - base
5
+
6
+ library:
7
+ exposed-modules: Pangram
8
+ source-dirs: src
9
+ dependencies:
10
+ # - foo # List here the packages you
11
+ # - bar # want to use in your solution.
12
+
13
+ tests:
14
+ test:
15
+ main: Tests.hs
16
+ source-dirs: test
17
+ dependencies:
18
+ - pangram
19
+ - hspec
@@ -0,0 +1,4 @@
1
+ module Pangram (isPangram) where
2
+
3
+ isPangram :: String -> Bool
4
+ isPangram text = error "You need to implement this function."
@@ -0,0 +1 @@
1
+ resolver: lts-8.2
@@ -0,0 +1,65 @@
1
+ {-# LANGUAGE RecordWildCards #-}
2
+
3
+ import Data.Foldable (for_)
4
+ import Test.Hspec (Spec, describe, it, shouldBe)
5
+ import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
6
+
7
+ import Pangram (isPangram)
8
+
9
+ main :: IO ()
10
+ main = hspecWith defaultConfig {configFastFail = True} specs
11
+
12
+ specs :: Spec
13
+ specs = describe "pangram" $
14
+ describe "isPangram" $ for_ cases test
15
+ where
16
+ test Case{..} = it description $ isPangram input `shouldBe` expected
17
+
18
+ -- Adapted from
19
+ -- Source: exercism/x-common/exercises/pangram/canonical-data.json
20
+ -- Version: 1.0.0
21
+ -- Date: 2017-03-28.
22
+
23
+ data Case = Case { description :: String
24
+ , input :: String
25
+ , expected :: Bool
26
+ }
27
+
28
+ cases :: [Case]
29
+ cases = [ Case { description = "sentence empty"
30
+ , input = ""
31
+ , expected = False
32
+ }
33
+ , Case { description = "pangram with only lower case"
34
+ , input = "the quick brown fox jumps over the lazy dog"
35
+ , expected = True
36
+ }
37
+ , Case { description = "missing character 'x'"
38
+ , input = "a quick movement of the enemy will jeopardize five gunboats"
39
+ , expected = False
40
+ }
41
+ , Case { description = "another missing character 'x'"
42
+ , input = "the quick brown fish jumps over the lazy dog"
43
+ , expected = False
44
+ }
45
+ , Case { description = "pangram with underscores"
46
+ , input = "the_quick_brown_fox_jumps_over_the_lazy_dog"
47
+ , expected = True
48
+ }
49
+ , Case { description = "pangram with numbers"
50
+ , input = "the 1 quick brown fox jumps over the 2 lazy dogs"
51
+ , expected = True
52
+ }
53
+ , Case { description = "missing letters replaced by numbers"
54
+ , input = "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog"
55
+ , expected = False
56
+ }
57
+ , Case { description = "pangram with mixed case and punctuation"
58
+ , input = "\"Five quacking Zephyrs jolt my wax bed.\""
59
+ , expected = True
60
+ }
61
+ , Case { description = "upper and lower case versions of the same character should not be counted separately"
62
+ , input = "the quick brown fox jumped over the lazy FOX"
63
+ , expected = False
64
+ }
65
+ ]
@@ -7,6 +7,9 @@ import static java.util.Collections.emptyList;
7
7
  import static java.util.Collections.singletonList;
8
8
  import static org.junit.Assert.assertEquals;
9
9
 
10
+ /*
11
+ * version: 1.1.0
12
+ */
10
13
  public final class FlattenerTest {
11
14
 
12
15
  private Flattener flattener;
@@ -16,6 +19,18 @@ public final class FlattenerTest {
16
19
  flattener = new Flattener();
17
20
  }
18
21
 
22
+ @Test
23
+ public void testFlatListIsPreserved() {
24
+ assertEquals(
25
+ asList(0, '1', "two"),
26
+ flattener.flatten(
27
+ asList(
28
+ 0,
29
+ '1',
30
+ "two")));
31
+ }
32
+
33
+ @Ignore
19
34
  @Test
20
35
  public void testASingleLevelOfNestingWithNoNulls() {
21
36
  assertEquals(
@@ -2,7 +2,7 @@ import java.util.Arrays;
2
2
  import java.util.List;
3
3
  import java.util.stream.Collectors;
4
4
 
5
- public class PigLatin {
5
+ public class PigLatinTranslator {
6
6
 
7
7
  public static final String AY = "ay";
8
8
  public static final String THR = "thr";
@@ -15,7 +15,7 @@ public class PigLatin {
15
15
  public static final String YT = "yt";
16
16
  public static final String VOWELS_REGEX = "[aeiou]";
17
17
 
18
- public static String translate(String sentence) {
18
+ public String translate(String sentence) {
19
19
  List<String> translatedWords = Arrays.asList(sentence.split(" "))
20
20
  .stream()
21
21
  .map(x -> translateWord(x))
@@ -24,7 +24,7 @@ public class PigLatin {
24
24
  return String.join(" ", translatedWords);
25
25
  }
26
26
 
27
- private static String translateWord(String word) {
27
+ private String translateWord(String word) {
28
28
  if (wordStartsWithVowelLike(word)) {
29
29
  return word + AY;
30
30
  }
@@ -44,16 +44,16 @@ public class PigLatin {
44
44
  return word.substring(1) + word.toCharArray()[0] + AY;
45
45
  }
46
46
 
47
- private static boolean wordStartsWithVowelLike(String word) {
47
+ private boolean wordStartsWithVowelLike(String word) {
48
48
  return word.startsWith(YT) || word.startsWith(XR) || word.substring(0, 1).matches(VOWELS_REGEX);
49
49
  }
50
50
 
51
- private static boolean wordStartsWithPrefixes(String word, String... prefixes) {
52
- return Arrays.asList(prefixes).stream()
53
- .anyMatch(x -> word.startsWith(x));
51
+ private boolean wordStartsWithPrefixes(String word, String... prefixes) {
52
+ return Arrays.stream(prefixes)
53
+ .anyMatch(word::startsWith);
54
54
  }
55
55
 
56
- private static boolean wordStartsWithConsonantAndQu(String word) {
56
+ private boolean wordStartsWithConsonantAndQu(String word) {
57
57
  return word.substring(1).startsWith(QU);
58
58
  }
59
59
  }
@@ -1,5 +1,4 @@
1
1
  import org.junit.Test;
2
- import org.junit.Ignore;
3
2
  import org.junit.runner.RunWith;
4
3
  import org.junit.runners.Parameterized;
5
4
 
@@ -9,7 +8,7 @@ import java.util.Collection;
9
8
  import static org.junit.Assert.assertEquals;
10
9
 
11
10
  @RunWith(Parameterized.class)
12
- public class PigLatinTest {
11
+ public class PigLatinTranslatorTest {
13
12
 
14
13
  private String englishPhrase;
15
14
  private String pigLatinTranslation;
@@ -59,14 +58,14 @@ public class PigLatinTest {
59
58
  });
60
59
  }
61
60
 
62
- public PigLatinTest(String englishPhrase, String pigLatinTranslation) {
61
+ public PigLatinTranslatorTest(String englishPhrase, String pigLatinTranslation) {
63
62
  this.englishPhrase = englishPhrase;
64
63
  this.pigLatinTranslation = pigLatinTranslation;
65
64
  }
66
65
 
67
-
68
66
  @Test
69
67
  public void test() {
70
- assertEquals(pigLatinTranslation, PigLatin.translate(englishPhrase));
68
+ assertEquals(pigLatinTranslation, new PigLatinTranslator().translate(englishPhrase));
71
69
  }
70
+
72
71
  }
@@ -1,9 +1,9 @@
1
1
  import java.util.ArrayList;
2
2
  import java.util.List;
3
3
 
4
- public class PrimeFactors {
4
+ public class PrimeFactorsCalculator {
5
5
 
6
- public static List<Long> getForNumber(long number) {
6
+ public List<Long> calculatePrimeFactorsOf(long number) {
7
7
  List<Long> primes = new ArrayList<>();
8
8
  long divisor = 2;
9
9
 
@@ -1,17 +1,17 @@
1
1
  import org.junit.Test;
2
- import org.junit.Ignore;
3
2
  import org.junit.runner.RunWith;
4
3
  import org.junit.runners.Parameterized;
5
4
  import org.junit.runners.Parameterized.Parameters;
6
5
 
7
6
  import java.util.Arrays;
8
7
  import java.util.Collection;
8
+ import java.util.Collections;
9
9
  import java.util.List;
10
10
 
11
11
  import static org.junit.Assert.assertEquals;
12
12
 
13
13
  @RunWith(Parameterized.class)
14
- public class PrimeFactorsTest {
14
+ public class PrimeFactorsCalculatorTest {
15
15
 
16
16
  private long input;
17
17
  private List<Long> expectedOutput;
@@ -19,9 +19,9 @@ public class PrimeFactorsTest {
19
19
  @Parameters(name="Prime factors of {0} = {1}")
20
20
  public static Collection<Object[]> data() {
21
21
  return Arrays.asList(new Object[][]{
22
- {1L, Arrays.asList()},
23
- {2L, Arrays.asList(2L)},
24
- {3L, Arrays.asList(3L)},
22
+ {1L, Collections.emptyList()},
23
+ {2L, Collections.singletonList(2L)},
24
+ {3L, Collections.singletonList(3L)},
25
25
  {4L, Arrays.asList(2L, 2L)},
26
26
  {6L, Arrays.asList(2L, 3L)},
27
27
  {8L, Arrays.asList(2L, 2L, 2L)},
@@ -33,14 +33,14 @@ public class PrimeFactorsTest {
33
33
  });
34
34
  }
35
35
 
36
- public PrimeFactorsTest(long input, List<Long> expectedOutput) {
36
+ public PrimeFactorsCalculatorTest(long input, List<Long> expectedOutput) {
37
37
  this.input = input;
38
38
  this.expectedOutput = expectedOutput;
39
39
  }
40
40
 
41
-
42
41
  @Test
43
42
  public void test() {
44
- assertEquals(expectedOutput, PrimeFactors.getForNumber(input));
43
+ assertEquals(expectedOutput, new PrimeFactorsCalculator().calculatePrimeFactorsOf(input));
45
44
  }
45
+
46
46
  }
@@ -2,8 +2,14 @@ import unittest
2
2
 
3
3
  from allergies import Allergies
4
4
 
5
+ # Python 2/3 compatibility
6
+ if not hasattr(unittest.TestCase, 'assertCountEqual'):
7
+ unittest.TestCase.assertCountEqual = unittest.TestCase.assertItemsEqual
5
8
 
6
- class AllergiesTests(unittest.TestCase):
9
+
10
+ # test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
11
+
12
+ class AllergiesTests():
7
13
  def test_no_allergies_means_not_allergic(self):
8
14
  allergies = Allergies(0)
9
15
  self.assertFalse(allergies.is_allergic_to('peanuts'))
@@ -13,7 +19,7 @@ class AllergiesTests(unittest.TestCase):
13
19
  def test_is_allergic_to_eggs(self):
14
20
  self.assertTrue(Allergies(1).is_allergic_to('eggs'))
15
21
 
16
- def test_has_the_right_allergies(self):
22
+ def test_allergic_to_eggs_in_addition_to_other_stuff(self):
17
23
  allergies = Allergies(5)
18
24
  self.assertTrue(allergies.is_allergic_to('eggs'))
19
25
  self.assertTrue(allergies.is_allergic_to('shellfish'))
@@ -22,19 +28,43 @@ class AllergiesTests(unittest.TestCase):
22
28
  def test_no_allergies_at_all(self):
23
29
  self.assertEqual(Allergies(0).lst, [])
24
30
 
31
+ def test_allergic_to_just_eggs(self):
32
+ self.assertEqual(Allergies(1).lst, ['eggs'])
33
+
25
34
  def test_allergic_to_just_peanuts(self):
26
35
  self.assertEqual(Allergies(2).lst, ['peanuts'])
27
36
 
37
+ def test_allergic_to_just_strawberries(self):
38
+ self.assertEqual(Allergies(8).lst, ['strawberries'])
39
+
40
+ def test_allergic_to_eggs_and_peanuts(self):
41
+ self.assertCountEqual(Allergies(3).lst, ['eggs', 'peanuts'])
42
+
43
+ def test_allergic_to_more_than_eggs_but_not_peanuts(self):
44
+ self.assertCountEqual(Allergies(5).lst, ['eggs', 'shellfish'])
45
+
46
+ def test_allergic_to_lots_of_stuff(self):
47
+ self.assertCountEqual(
48
+ Allergies(248).lst,
49
+ ['strawberries', 'tomatoes', 'chocolate', 'pollen', 'cats'])
50
+
28
51
  def test_allergic_to_everything(self):
29
- self.assertEqual(
30
- sorted(Allergies(255).lst),
31
- sorted(('eggs peanuts shellfish strawberries tomatoes '
32
- 'chocolate pollen cats').split()))
52
+ self.assertCountEqual(
53
+ Allergies(255).lst, [
54
+ 'eggs', 'peanuts', 'shellfish', 'strawberries', 'tomatoes',
55
+ 'chocolate', 'pollen', 'cats'
56
+ ])
33
57
 
34
- @unittest.skip('Extra Credit: Passes with a specific type of solution')
35
- def test_ignore_non_allergen_score_parts(self):
58
+ def test_ignore_non_allergen_score_parts_only_eggs(self):
36
59
  self.assertEqual(Allergies(257).lst, ['eggs'])
37
60
 
61
+ def test_ignore_non_allergen_score_parts(self):
62
+ self.assertCountEqual(
63
+ Allergies(509).lst, [
64
+ 'eggs', 'shellfish', 'strawberries', 'tomatoes', 'chocolate',
65
+ 'pollen', 'cats'
66
+ ])
67
+
38
68
 
39
69
  if __name__ == '__main__':
40
70
  unittest.main()
@@ -3,6 +3,8 @@ import unittest
3
3
  from pig_latin import translate
4
4
 
5
5
 
6
+ # test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
7
+
6
8
  class PigLatinTests(unittest.TestCase):
7
9
  def test_word_beginning_with_a(self):
8
10
  self.assertEqual(translate("apple"), "appleay")
@@ -10,19 +12,40 @@ class PigLatinTests(unittest.TestCase):
10
12
  def test_word_beginning_with_e(self):
11
13
  self.assertEqual(translate("ear"), "earay")
12
14
 
15
+ def test_word_beginning_with_i(self):
16
+ self.assertEqual(translate("igloo"), "iglooay")
17
+
18
+ def test_word_beginning_with_o(self):
19
+ self.assertEqual(translate("object"), "objectay")
20
+
21
+ def test_word_beginning_with_u(self):
22
+ self.assertEqual(translate("under"), "underay")
23
+
24
+ def test_word_beginning_with_a_vowel_and_followed_by_a_qu(self):
25
+ self.assertEqual(translate("equal"), "equalay")
26
+
13
27
  def test_word_beginning_with_p(self):
14
28
  self.assertEqual(translate("pig"), "igpay")
15
29
 
16
30
  def test_word_beginning_with_k(self):
17
31
  self.assertEqual(translate("koala"), "oalakay")
18
32
 
33
+ def test_word_beginning_with_y(self):
34
+ self.assertEqual(translate("yellow"), "ellowyay")
35
+
36
+ def test_word_beginning_with_x(self):
37
+ self.assertEqual(translate("xenon"), "enonxay")
38
+
39
+ def test_word_beginning_with_q_without_a_following_u(self):
40
+ self.assertEqual(translate("qat"), "atqay")
41
+
19
42
  def test_word_beginning_with_ch(self):
20
43
  self.assertEqual(translate("chair"), "airchay")
21
44
 
22
45
  def test_word_beginning_with_qu(self):
23
46
  self.assertEqual(translate("queen"), "eenquay")
24
47
 
25
- def test_word_beginning_with_squ(self):
48
+ def test_word_beginning_with_qu_and_a_preceding_consonant(self):
26
49
  self.assertEqual(translate("square"), "aresquay")
27
50
 
28
51
  def test_word_beginning_with_th(self):
@@ -34,21 +57,15 @@ class PigLatinTests(unittest.TestCase):
34
57
  def test_word_beginning_with_sch(self):
35
58
  self.assertEqual(translate("school"), "oolschay")
36
59
 
37
- def test_translates_phrase(self):
38
- self.assertEqual(translate("quick fast run"), "ickquay astfay unray")
39
-
40
- def test_word_beginning_with_ye(self):
41
- self.assertEqual(translate("yellow"), "ellowyay")
42
-
43
60
  def test_word_beginning_with_yt(self):
44
61
  self.assertEqual(translate("yttria"), "yttriaay")
45
62
 
46
- def test_word_beginning_with_xe(self):
47
- self.assertEqual(translate("xenon"), "enonxay")
48
-
49
63
  def test_word_beginning_with_xr(self):
50
64
  self.assertEqual(translate("xray"), "xrayay")
51
65
 
66
+ def test_a_whole_phrase(self):
67
+ self.assertEqual(translate("quick fast run"), "ickquay astfay unray")
68
+
52
69
 
53
70
  if __name__ == '__main__':
54
71
  unittest.main()
File without changes
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.0.8.42
4
+ version: 2.0.8.43
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-04-06 00:00:00.000000000 Z
11
+ date: 2017-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -1860,6 +1860,7 @@ files:
1860
1860
  - tracks/csharp/exercises/zebra-puzzle/ZebraPuzzle.csproj
1861
1861
  - tracks/csharp/exercises/zebra-puzzle/ZebraPuzzleTest.cs
1862
1862
  - tracks/csharp/exercises/zipper/Example.cs
1863
+ - tracks/csharp/exercises/zipper/HINTS.md
1863
1864
  - tracks/csharp/exercises/zipper/Zipper.cs
1864
1865
  - tracks/csharp/exercises/zipper/Zipper.csproj
1865
1866
  - tracks/csharp/exercises/zipper/ZipperTest.cs
@@ -1912,6 +1913,7 @@ files:
1912
1913
  - tracks/csharp/generators/generate.sh
1913
1914
  - tracks/csharp/img/icon.png
1914
1915
  - tracks/delphi/.git
1916
+ - tracks/delphi/.github/stale.yml
1915
1917
  - tracks/delphi/.gitignore
1916
1918
  - tracks/delphi/.travis.yml
1917
1919
  - tracks/delphi/LICENSE
@@ -3669,6 +3671,12 @@ files:
3669
3671
  - tracks/haskell/exercises/accumulate/src/Accumulate.hs
3670
3672
  - tracks/haskell/exercises/accumulate/stack.yaml
3671
3673
  - tracks/haskell/exercises/accumulate/test/Tests.hs
3674
+ - tracks/haskell/exercises/acronym/examples/success-standard/package.yaml
3675
+ - tracks/haskell/exercises/acronym/examples/success-standard/src/Acronym.hs
3676
+ - tracks/haskell/exercises/acronym/package.yaml
3677
+ - tracks/haskell/exercises/acronym/src/Acronym.hs
3678
+ - tracks/haskell/exercises/acronym/stack.yaml
3679
+ - tracks/haskell/exercises/acronym/test/Tests.hs
3672
3680
  - tracks/haskell/exercises/all-your-base/examples/success-standard/package.yaml
3673
3681
  - tracks/haskell/exercises/all-your-base/examples/success-standard/src/Base.hs
3674
3682
  - tracks/haskell/exercises/all-your-base/package.yaml
@@ -3744,6 +3752,12 @@ files:
3744
3752
  - tracks/haskell/exercises/bowling/src/Bowling.hs
3745
3753
  - tracks/haskell/exercises/bowling/stack.yaml
3746
3754
  - tracks/haskell/exercises/bowling/test/Tests.hs
3755
+ - tracks/haskell/exercises/bracket-push/examples/success-standard/package.yaml
3756
+ - tracks/haskell/exercises/bracket-push/examples/success-standard/src/Brackets.hs
3757
+ - tracks/haskell/exercises/bracket-push/package.yaml
3758
+ - tracks/haskell/exercises/bracket-push/src/Brackets.hs
3759
+ - tracks/haskell/exercises/bracket-push/stack.yaml
3760
+ - tracks/haskell/exercises/bracket-push/test/Tests.hs
3747
3761
  - tracks/haskell/exercises/change/examples/success-standard/package.yaml
3748
3762
  - tracks/haskell/exercises/change/examples/success-standard/src/Change.hs
3749
3763
  - tracks/haskell/exercises/change/package.yaml
@@ -3959,6 +3973,12 @@ files:
3959
3973
  - tracks/haskell/exercises/palindrome-products/src/Palindromes.hs
3960
3974
  - tracks/haskell/exercises/palindrome-products/stack.yaml
3961
3975
  - tracks/haskell/exercises/palindrome-products/test/Tests.hs
3976
+ - tracks/haskell/exercises/pangram/examples/success-standard/package.yaml
3977
+ - tracks/haskell/exercises/pangram/examples/success-standard/src/Pangram.hs
3978
+ - tracks/haskell/exercises/pangram/package.yaml
3979
+ - tracks/haskell/exercises/pangram/src/Pangram.hs
3980
+ - tracks/haskell/exercises/pangram/stack.yaml
3981
+ - tracks/haskell/exercises/pangram/test/Tests.hs
3962
3982
  - tracks/haskell/exercises/parallel-letter-frequency/HINTS.md
3963
3983
  - tracks/haskell/exercises/parallel-letter-frequency/examples/success-standard/package.yaml
3964
3984
  - tracks/haskell/exercises/parallel-letter-frequency/examples/success-standard/src/Frequency.hs
@@ -4448,13 +4468,13 @@ files:
4448
4468
  - tracks/java/exercises/phone-number/src/main/java/.keep
4449
4469
  - tracks/java/exercises/phone-number/src/test/java/PhoneNumberTest.java
4450
4470
  - tracks/java/exercises/pig-latin/build.gradle
4451
- - tracks/java/exercises/pig-latin/src/example/java/PigLatin.java
4471
+ - tracks/java/exercises/pig-latin/src/example/java/PigLatinTranslator.java
4452
4472
  - tracks/java/exercises/pig-latin/src/main/java/.keep
4453
- - tracks/java/exercises/pig-latin/src/test/java/PigLatinTest.java
4473
+ - tracks/java/exercises/pig-latin/src/test/java/PigLatinTranslatorTest.java
4454
4474
  - tracks/java/exercises/prime-factors/build.gradle
4455
- - tracks/java/exercises/prime-factors/src/example/java/PrimeFactors.java
4475
+ - tracks/java/exercises/prime-factors/src/example/java/PrimeFactorsCalculator.java
4456
4476
  - tracks/java/exercises/prime-factors/src/main/java/.keep
4457
- - tracks/java/exercises/prime-factors/src/test/java/PrimeFactorsTest.java
4477
+ - tracks/java/exercises/prime-factors/src/test/java/PrimeFactorsCalculatorTest.java
4458
4478
  - tracks/java/exercises/pythagorean-triplet/build.gradle
4459
4479
  - tracks/java/exercises/pythagorean-triplet/src/example/java/PythagoreanTriplet.java
4460
4480
  - tracks/java/exercises/pythagorean-triplet/src/main/java/PythagoreanTriplet.java
@@ -7036,6 +7056,7 @@ files:
7036
7056
  - tracks/ruby/.git
7037
7057
  - tracks/ruby/.github/ISSUE_TEMPLATE.md
7038
7058
  - tracks/ruby/.github/PULL_REQUEST_TEMPLATE.md
7059
+ - tracks/ruby/.github/stale.yml
7039
7060
  - tracks/ruby/.gitignore
7040
7061
  - tracks/ruby/.rubocop.yml
7041
7062
  - tracks/ruby/.travis.yml