trackler 2.0.3.3 → 2.0.3.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f53c82944593257de8cc399d3860e5b259356f7
4
- data.tar.gz: bc1988328ae552a72a96ac4f667d29c0462234ba
3
+ metadata.gz: 36080e740c50fc72852fc37ec458b86bfbfc9e44
4
+ data.tar.gz: a5c5c21f888bc1a2c926b81bfa7cf0c3b529558a
5
5
  SHA512:
6
- metadata.gz: 853a83ae347321c14cb1158f7c5fea7ac57d4ba766308311c596b30b34be347d5a8b97bd29a885f6a0fb07091a741884a4f5a1b6d64a77889dfdba713dc3b5a1
7
- data.tar.gz: c109355bbb872dbb92259dd4770bf013430c4e5f78dca6bf7d0d08289799c0b681a07deea6fbae1fad6ab5b2f8b1571d045bb46843738bc816bcfa32deacc6b7
6
+ metadata.gz: 54197c20523de15b52d62db122611be7b844ce329283a3d2bb59840899a7545bed21c0f44e6e2c094765b546d46ee4f95a311941cc23a4761d1f87f50fbce44d
7
+ data.tar.gz: 1e14225a99cab48c3125db478b9d50440aad4109efbdb88a5fd77cc383c29bfc9cdcb9295d6920ea7772d9e56a1f1f0eec8dc774ff8168c8d0d09a0ddd2821e9
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.3.3"
2
+ VERSION = "2.0.3.4"
3
3
  end
@@ -0,0 +1 @@
1
+ tracks/haskell/exercises/pov/../../common/stack.yaml
@@ -0,0 +1 @@
1
+ resolver: lts-7.9
@@ -16,7 +16,10 @@
16
16
  {
17
17
  "slug": "leap",
18
18
  "difficulty": 1,
19
- "topics": []
19
+ "topics": [
20
+ "Integers",
21
+ "Booleans"
22
+ ]
20
23
  },
21
24
  {
22
25
  "slug": "hamming",
@@ -4,29 +4,37 @@ open Difference_of_squares
4
4
 
5
5
  let ae exp got _test_ctxt = assert_equal exp got
6
6
 
7
- let tests =
8
- [
9
- "square of sum 5">::
10
- ae 225 (square_of_sum 5);
11
- "square of sum 10">::
12
- ae 3025 (square_of_sum 10);
13
- "square of sum 100">::
14
- ae 25502500 (square_of_sum 100);
15
- "sum of squares 5">::
16
- ae 55 (sum_of_squares 5);
17
- "sum of squares 10">::
18
- ae 385 (sum_of_squares 10);
19
- "sum of squares 5">::
20
- ae 338350 (sum_of_squares 100);
21
- "difference of squares 0">::
22
- ae 0 (difference_of_squares 0);
23
- "difference of squares 5">::
24
- ae 170 (difference_of_squares 5);
25
- "difference of squares 10">::
26
- ae 2640 (difference_of_squares 10);
27
- "difference of squares 100">::
28
- ae 25164150 (difference_of_squares 100);
7
+ let square_of_sum_tests = [
8
+ "square of sum 5" >::
9
+ ae 225 (square_of_sum 5);
10
+ "square of sum 10" >::
11
+ ae 3025 (square_of_sum 10);
12
+ "square of sum 100" >::
13
+ ae 25502500 (square_of_sum 100);
14
+ ]
15
+
16
+ let sum_of_squares_tests = [
17
+ "sum of squares 5" >::
18
+ ae 55 (sum_of_squares 5);
19
+ "sum of squares 10" >::
20
+ ae 385 (sum_of_squares 10);
21
+ "sum of squares 100" >::
22
+ ae 338350 (sum_of_squares 100);
23
+ ]
24
+
25
+ let difference_of_squares_tests = [
26
+ "difference of squares 0" >::
27
+ ae 0 (difference_of_squares 0);
28
+ "difference of squares 5" >::
29
+ ae 170 (difference_of_squares 5);
30
+ "difference of squares 10" >::
31
+ ae 2640 (difference_of_squares 10);
32
+ "difference of squares 100" >::
33
+ ae 25164150 (difference_of_squares 100);
29
34
  ]
30
35
 
31
36
  let () =
32
- run_test_tt_main ("difference of squares tests" >::: tests)
37
+ run_test_tt_main (
38
+ "difference of squares tests" >:::
39
+ List.concat [square_of_sum_tests; sum_of_squares_tests; difference_of_squares_tests]
40
+ )
@@ -1,5 +1,6 @@
1
1
  open Core.Std
2
2
  open OUnit2
3
+ open Minesweeper
3
4
 
4
5
  let format_board strings =
5
6
  let width = match strings with
@@ -13,45 +14,118 @@ let format_board strings =
13
14
  let ae exp got =
14
15
  assert_equal exp got ~cmp:(List.equal ~equal:String.equal) ~printer:format_board
15
16
 
16
- let clean strings =
17
- List.map strings ~f:(String.map ~f:(function '*' -> '*' | _ -> ' '))
18
-
19
- let tests =
20
- ["zero size board">::(fun _ ->
21
- ae [] (Minesweeper.annotate []));
22
- "empty board">::(fun _ ->
17
+ let tests = [
18
+ "no rows" >:: (fun _ ->
19
+ let b = [] in
20
+ let expected = [] in
21
+ ae expected (annotate b)
22
+ );
23
+ "no columns" >:: (fun _ ->
24
+ let b = [""] in
25
+ let expected = [""] in
26
+ ae expected (annotate b)
27
+ );
28
+ "no mines" >:: (fun _ ->
23
29
  let b = [" ";
24
30
  " ";
25
31
  " "] in
26
- ae b (Minesweeper.annotate b));
27
- "board full of mines">::(fun _ ->
32
+ let expected = [" ";
33
+ " ";
34
+ " "] in
35
+ ae expected (annotate b)
36
+ );
37
+ "board with only mines" >:: (fun _ ->
28
38
  let b = ["***";
29
39
  "***";
30
40
  "***"] in
31
- ae b (Minesweeper.annotate b));
32
- "surrounded">::(fun _ ->
41
+ let expected = ["***";
42
+ "***";
43
+ "***"] in
44
+ ae expected (annotate b)
45
+ );
46
+ "mine surrounded by spaces" >:: (fun _ ->
47
+ let b = [" ";
48
+ " * ";
49
+ " "] in
50
+ let expected = ["111";
51
+ "1*1";
52
+ "111"] in
53
+ ae expected (annotate b)
54
+ );
55
+ "space surrounded by mines" >:: (fun _ ->
33
56
  let b = ["***";
34
- "*8*";
57
+ "* *";
35
58
  "***"] in
36
- ae b (Minesweeper.annotate (clean b)));
37
- "horizontal line">::(fun _ ->
38
- let b = ["1*2*1"] in
39
- ae b (Minesweeper.annotate (clean b)));
40
- "vertical line">::(fun _ ->
41
- let b = ["1";
42
- "*";
43
- "2";
44
- "*";
45
- "1"] in
46
- ae b (Minesweeper.annotate (clean b)));
47
- "cross">::(fun _ ->
48
- let b = [" 2*2 ";
49
- "25*52";
59
+ let expected = ["***";
60
+ "*8*";
61
+ "***"] in
62
+ ae expected (annotate b)
63
+ );
64
+ "horizontal line" >:: (fun _ ->
65
+ let b = [" * * "] in
66
+ let expected = ["1*2*1"] in
67
+ ae expected (annotate b)
68
+ );
69
+ "horizontal line, mines at edges" >:: (fun _ ->
70
+ let b = ["* *"] in
71
+ let expected = ["*1 1*"] in
72
+ ae expected (annotate b)
73
+ );
74
+ "vertical line" >:: (fun _ ->
75
+ let b = [" ";
76
+ "*";
77
+ " ";
78
+ "*";
79
+ " "] in
80
+ let expected = ["1";
81
+ "*";
82
+ "2";
83
+ "*";
84
+ "1"] in
85
+ ae expected (annotate b)
86
+ );
87
+ "vertical line, mines at edges" >:: (fun _ ->
88
+ let b = ["*";
89
+ " ";
90
+ " ";
91
+ " ";
92
+ "*"] in
93
+ let expected = ["*";
94
+ "1";
95
+ " ";
96
+ "1";
97
+ "*"] in
98
+ ae expected (annotate b)
99
+ );
100
+ "cross" >:: (fun _ ->
101
+ let b = [" * ";
102
+ " * ";
50
103
  "*****";
51
- "25*52";
52
- " 2*2 "] in
53
- ae b (Minesweeper.annotate (clean b)));
54
- ]
104
+ " * ";
105
+ " * "] in
106
+ let expected = [" 2*2 ";
107
+ "25*52";
108
+ "*****";
109
+ "25*52";
110
+ " 2*2 "] in
111
+ ae expected (annotate b)
112
+ );
113
+ "large board" >:: (fun _ ->
114
+ let b = [" * * ";
115
+ " * ";
116
+ " * ";
117
+ " * *";
118
+ " * * ";
119
+ " "] in
120
+ let expected = ["1*22*1";
121
+ "12*322";
122
+ " 123*2";
123
+ "112*4*";
124
+ "1*22*2";
125
+ "111111"] in
126
+ ae expected (annotate b)
127
+ );
128
+ ]
55
129
 
56
130
  let () =
57
131
  run_test_tt_main ("minesweeper tests" >::: tests)
@@ -0,0 +1,28 @@
1
+ open Core.Std
2
+ open OUnit2
3
+ open Minesweeper
4
+
5
+ let format_board strings =
6
+ let width = match strings with
7
+ | [] -> 0
8
+ | (s::_) -> String.length s in
9
+ let border_line = "+" ^ String.make width '-' ^ "+\n" in
10
+ let line s = "|" ^ s ^ "|\n" in
11
+ "\n" ^ border_line ^ String.concat (List.map strings ~f:line) ^ border_line
12
+
13
+ (* Assert Equals *)
14
+ let ae exp got =
15
+ assert_equal exp got ~cmp:(List.equal ~equal:String.equal) ~printer:format_board
16
+
17
+ let tests = [
18
+ (* TEST
19
+ "$description" >:: (fun _ ->
20
+ let b = $input in
21
+ let expected = $expected in
22
+ ae expected (annotate b)
23
+ );
24
+ END TEST *)
25
+ ]
26
+
27
+ let () =
28
+ run_test_tt_main ("minesweeper tests" >::: tests)
@@ -17,87 +17,137 @@
17
17
  {
18
18
  "slug": "hello-world",
19
19
  "difficulty": 1,
20
- "topics": []
20
+ "topics": [
21
+ "Text formatting",
22
+ "Optional values"
23
+ ]
21
24
  },
22
25
  {
23
26
  "slug": "hamming",
24
27
  "difficulty": 2,
25
- "topics": []
28
+ "topics": [
29
+ "Strings",
30
+ "Filtering"
31
+ ]
26
32
  },
27
33
  {
28
34
  "slug": "gigasecond",
29
35
  "difficulty": 2,
30
- "topics": []
36
+ "topics": [
37
+ "Dates"
38
+ ]
31
39
  },
32
40
  {
33
41
  "slug": "bob",
34
42
  "difficulty": 4,
35
- "topics": []
43
+ "topics": [
44
+ "Strings",
45
+ "Control-flow (if-else statements)"
46
+ ]
36
47
  },
37
48
  {
38
49
  "slug": "pangram",
39
50
  "difficulty": 4,
40
- "topics": []
51
+ "topics": [
52
+ "Strings"
53
+ ]
41
54
  },
42
55
  {
43
56
  "slug": "rna-transcription",
44
57
  "difficulty": 3,
45
- "topics": []
58
+ "topics": [
59
+ "Strings",
60
+ "Transforming"
61
+ ]
46
62
  },
47
63
  {
48
64
  "slug": "raindrops",
49
65
  "difficulty": 6,
50
- "topics": []
66
+ "topics": [
67
+ "Text formatting",
68
+ "Filtering"
69
+ ]
51
70
  },
52
71
  {
53
72
  "slug": "isogram",
54
73
  "difficulty": 4,
55
- "topics": []
74
+ "topics": [
75
+ "Strings",
76
+ "Filtering"
77
+ ]
56
78
  },
57
79
  {
58
80
  "slug": "difference-of-squares",
59
81
  "difficulty": 2,
60
- "topics": []
82
+ "topics": [
83
+ "Integers"
84
+ ]
61
85
  },
62
86
  {
63
87
  "slug": "largest-series-product",
64
88
  "difficulty": 5,
65
- "topics": []
89
+ "topics": [
90
+ "Strings",
91
+ "Integers",
92
+ "Transforming"
93
+ ]
66
94
  },
67
95
  {
68
96
  "slug": "roman-numerals",
69
97
  "difficulty": 4,
70
- "topics": []
98
+ "topics": [
99
+ "Control-flow (loops)",
100
+ "Transforming"
101
+ ]
71
102
  },
72
103
  {
73
104
  "slug": "sieve",
74
105
  "difficulty": 1,
75
- "topics": []
106
+ "topics": [
107
+ "Filtering",
108
+ "Mathematics"
109
+ ]
76
110
  },
77
111
  {
78
112
  "slug": "pig-latin",
79
113
  "difficulty": 4,
80
- "topics": []
114
+ "topics": [
115
+ "Strings",
116
+ "Transforming"
117
+ ]
81
118
  },
82
119
  {
83
120
  "slug": "robot-name",
84
121
  "difficulty": 3,
85
- "topics": []
122
+ "topics": [
123
+ "Randomness",
124
+ "Strings",
125
+ "Classes"
126
+ ]
86
127
  },
87
128
  {
88
129
  "slug": "leap",
89
130
  "difficulty": 1,
90
- "topics": []
131
+ "topics": [
132
+ "Integers"
133
+ ]
91
134
  },
92
135
  {
93
136
  "slug": "word-count",
94
137
  "difficulty": 1,
95
- "topics": []
138
+ "topics": [
139
+ "Strings",
140
+ "Dictionaries",
141
+ "Transforming"
142
+ ]
96
143
  },
97
144
  {
98
145
  "slug": "anagram",
99
146
  "difficulty": 1,
100
- "topics": []
147
+ "topics": [
148
+ "Strings",
149
+ "Filtering"
150
+ ]
101
151
  },
102
152
  {
103
153
  "slug": "trinary",
@@ -107,17 +157,27 @@
107
157
  {
108
158
  "slug": "bowling",
109
159
  "difficulty": 1,
110
- "topics": []
160
+ "topics": [
161
+ "Algorithms",
162
+ "Control-flow (loops)"
163
+ ]
111
164
  },
112
165
  {
113
166
  "slug": "clock",
114
167
  "difficulty": 1,
115
- "topics": []
168
+ "topics": [
169
+ "Time",
170
+ "Structural equality"
171
+ ]
116
172
  },
117
173
  {
118
174
  "slug": "wordy",
119
175
  "difficulty": 1,
120
- "topics": []
176
+ "topics": [
177
+ "Parsing",
178
+ "Strings",
179
+ "Transforming"
180
+ ]
121
181
  },
122
182
  {
123
183
  "slug": "connect",
@@ -127,32 +187,51 @@
127
187
  {
128
188
  "slug": "minesweeper",
129
189
  "difficulty": 1,
130
- "topics": []
190
+ "topics": [
191
+ "Parsing",
192
+ "Transforming"
193
+ ]
131
194
  },
132
195
  {
133
196
  "slug": "change",
134
197
  "difficulty": 1,
135
- "topics": []
198
+ "topics": [
199
+ "Integers",
200
+ "Arrays"
201
+ ]
136
202
  },
137
203
  {
138
204
  "slug": "phone-number",
139
205
  "difficulty": 1,
140
- "topics": []
206
+ "topics": [
207
+ "Parsing",
208
+ "Transforming"
209
+ ]
141
210
  },
142
211
  {
143
212
  "slug": "beer-song",
144
213
  "difficulty": 1,
145
- "topics": []
214
+ "topics": [
215
+ "Text formatting",
216
+ "Algorithms"
217
+ ]
146
218
  },
147
219
  {
148
220
  "slug": "atbash-cipher",
149
221
  "difficulty": 1,
150
- "topics": []
222
+ "topics": [
223
+ "Strings",
224
+ "Algorithms",
225
+ "Transforming"
226
+ ]
151
227
  },
152
228
  {
153
229
  "slug": "bracket-push",
154
230
  "difficulty": 1,
155
- "topics": []
231
+ "topics": [
232
+ "Parsing",
233
+ "Strings"
234
+ ]
156
235
  },
157
236
  {
158
237
  "slug": "binary",
@@ -162,42 +241,67 @@
162
241
  {
163
242
  "slug": "accumulate",
164
243
  "difficulty": 1,
165
- "topics": []
244
+ "topics": [
245
+ "Extension methods",
246
+ "Sequences",
247
+ "Transforming"
248
+ ]
166
249
  },
167
250
  {
168
251
  "slug": "variable-length-quantity",
169
252
  "difficulty": 1,
170
- "topics": []
253
+ "topics": [
254
+ "Bitwise operations",
255
+ "Algorithms"
256
+ ]
171
257
  },
172
258
  {
173
259
  "slug": "acronym",
174
260
  "difficulty": 1,
175
- "topics": []
261
+ "topics": [
262
+ "Strings",
263
+ "Transforming"
264
+ ]
176
265
  },
177
266
  {
178
267
  "slug": "nucleotide-count",
179
268
  "difficulty": 1,
180
- "topics": []
269
+ "topics": [
270
+ "Dictionaries",
271
+ "Strings"
272
+ ]
181
273
  },
182
274
  {
183
275
  "slug": "triangle",
184
276
  "difficulty": 1,
185
- "topics": []
277
+ "topics": [
278
+ "Integers",
279
+ "Enumerations"
280
+ ]
186
281
  },
187
282
  {
188
283
  "slug": "etl",
189
284
  "difficulty": 1,
190
- "topics": []
285
+ "topics": [
286
+ "Dictionaries",
287
+ "Lists",
288
+ "Transforming"
289
+ ]
191
290
  },
192
291
  {
193
292
  "slug": "space-age",
194
293
  "difficulty": 1,
195
- "topics": []
294
+ "topics": [
295
+ "Floating-point numbers"
296
+ ]
196
297
  },
197
298
  {
198
299
  "slug": "allergies",
199
300
  "difficulty": 3,
200
- "topics": []
301
+ "topics": [
302
+ "Bitwise operations",
303
+ "Filtering"
304
+ ]
201
305
  },
202
306
  {
203
307
  "slug": "markdown",
@@ -1,37 +1,76 @@
1
1
  <?php
2
-
3
2
  class Robot
4
3
  {
5
- protected $name = null;
6
-
7
- protected $alphabet = '';
4
+ private $name;
8
5
 
9
6
  public function __construct()
10
7
  {
11
- $this->alphabet = array_flip(str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZ'));
8
+ $this->reset();
12
9
  }
13
10
 
11
+ /**
12
+ * Get Robot name
13
+ *
14
+ * @return string
15
+ */
14
16
  public function getName()
15
17
  {
16
- if (is_null($this->name)) {
17
- $this->name = sprintf('%s%s', $this->getPrefix(), $this->getSuffix());
18
- }
19
-
20
18
  return $this->name;
21
19
  }
22
20
 
23
- protected function getPrefix()
21
+ /**
22
+ * Reset name
23
+ */
24
+ public function reset()
25
+ {
26
+ $this->name = NamesRegistry::connect()->getNewName();
27
+ }
28
+ }
29
+
30
+ class NamesRegistry
31
+ {
32
+ private $names = [];
33
+ private static $letters;
34
+ private static $registry;
35
+
36
+ private function __construct()
24
37
  {
25
- return implode('', array_rand($this->alphabet, 2));
38
+
26
39
  }
27
40
 
28
- protected function getSuffix()
41
+ /**
42
+ * Get NamesRegistry singleton
43
+ *
44
+ * @return NamesRegistry
45
+ */
46
+ public static function connect()
29
47
  {
30
- return strval(rand(100, 999));
48
+ if (empty(self::$registry)) {
49
+ self::$registry = new NamesRegistry();
50
+ self::$letters = range('A', 'Z');
51
+ }
52
+ return self::$registry;
31
53
  }
32
54
 
33
- public function reset()
55
+ /**
56
+ * Get new unique robot name
57
+ *
58
+ * @todo Names rotation not implemented. Task requires all robots
59
+ * to have unique names even if there are obsolete names.
60
+ * @todo If there are plans to use Robot::reset() more than at least 200-300k times,
61
+ * it should be better to generate the full list of possible names at __construct
62
+ * and randomly reduce it on demand.
63
+ * @todo No fallback in case of over 676000 names.
64
+ *
65
+ * @return string New Robot name *
66
+ */
67
+ public function getNewName()
34
68
  {
35
- $this->name = null;
69
+ do {
70
+ shuffle(self::$letters);
71
+ $name = self::$letters[0] . self::$letters[1] . sprintf('%03d', mt_rand(0, 999));
72
+ } while (!empty($this->names[$name]));
73
+ $this->names[$name] = true;
74
+ return $name;
36
75
  }
37
76
  }
@@ -48,4 +48,27 @@ class RobotTest extends PHPUnit_Framework_TestCase
48
48
 
49
49
  $this->assertRegExp('/\w{2}\d{3}/', $name2);
50
50
  }
51
+
52
+ public function testNameArentRecycled()
53
+ {
54
+ $names = [];
55
+
56
+ for ($i = 0; $i < 10000; $i++) {
57
+ $name = $this->robot->getName();
58
+ $this->assertArrayNotHasKey($name, $names, sprintf('Name %s reissued after Reset.', $name));
59
+ $names[$name] = true;
60
+ $this->robot->reset();
61
+ }
62
+ }
63
+
64
+ public function testNameUniquenessManyRobots()
65
+ {
66
+ $names = [];
67
+
68
+ for ($i = 0; $i < 10000; $i++) {
69
+ $name = (new Robot())->getName();
70
+ $this->assertArrayNotHasKey($name, $names, sprintf('Name %s reissued after %d robots', $name, $i));
71
+ $names[$name] = true;
72
+ }
73
+ }
51
74
  }
@@ -0,0 +1,3 @@
1
+ ## Hints
2
+ Note that `GregorianCalendar` is a mutable object.
3
+ You should not change this mutable object to avoid any side effects!
@@ -0,0 +1,10 @@
1
+ ## Hints
2
+ For something a little different you might also try a solution with an `unfold` function.
3
+ You are probably already familiar with `foldLeft/Right`: "map" a whole collection into something else (usually a non-collection).
4
+ `unfoldLeft/Right` are the "inverse" operations: "map" something (usually a non-collection) into a collection.
5
+ So `unfold`ing is a logical addition to and part of the FP standard repertoire.
6
+
7
+ This exercise can be seen as a case for `unfold`ing: "map" an `Int` into a `String` (which is of course implicitly a `Seq[Char]`).
8
+
9
+ Unfortunately `unfoldLeft/Right` is not included in Scala's collection library.
10
+ But you can take the implementation from [here](http://daily-scala.blogspot.de/2009/09/unfoldleft-and-right.html).
@@ -492,6 +492,14 @@
492
492
  "Transforming"
493
493
  ]
494
494
  },
495
+ {
496
+ "difficulty": 6,
497
+ "slug": "transpose",
498
+ "topics": [
499
+ "Strings",
500
+ "Transforming"
501
+ ]
502
+ },
495
503
  {
496
504
  "difficulty": 7,
497
505
  "slug": "bracket-push",
@@ -0,0 +1,35 @@
1
+ struct Transpose {
2
+ static func transpose(_ input: [String]) -> [String] {
3
+ let maxLineLength = input.map { $0.characters.count }.max()
4
+
5
+ guard let maxLength = maxLineLength else {
6
+ return []
7
+ }
8
+
9
+ var result = [String](repeatElement("", count: maxLength))
10
+
11
+ for i in 0..<maxLength {
12
+ for line in input {
13
+ if let start = line.index(line.startIndex, offsetBy: i, limitedBy: line.endIndex),
14
+ let end = line.index(start, offsetBy: 1, limitedBy: line.endIndex) {
15
+ let character = line[start..<end]
16
+ result[i].append(character)
17
+ } else {
18
+ result[i].append(" ")
19
+ }
20
+ }
21
+ }
22
+
23
+ return result.map { stripTrailingWhitespace($0) }
24
+ }
25
+
26
+ private static func stripTrailingWhitespace(_ input: String) -> String {
27
+ var result = input
28
+
29
+ while result.hasSuffix(" ") {
30
+ result.remove(at: result.index(before: result.endIndex))
31
+ }
32
+
33
+ return result
34
+ }
35
+ }
@@ -0,0 +1,135 @@
1
+ #if swift(>=3.0)
2
+ import XCTest
3
+ #endif
4
+
5
+ class TransposeTest: XCTestCase {
6
+
7
+ func testEmptyInput() {
8
+ XCTAssertEqual(Transpose.transpose([]), [])
9
+ }
10
+
11
+ func testTwoCharactersInARow() {
12
+ XCTAssertEqual(Transpose.transpose(["A1"]), ["A", "1"])
13
+ }
14
+
15
+ func testTwoCharactersInAColumn() {
16
+ XCTAssertEqual(Transpose.transpose(["A", "1"]), ["A1"])
17
+ }
18
+
19
+ func testSimple() {
20
+ XCTAssertEqual(Transpose.transpose(["ABC", "123"]), ["A1", "B2", "C3"])
21
+ }
22
+
23
+ func testSingleLine() {
24
+ let expected = ["S", "i", "n", "g", "l", "e", "", "l", "i", "n", "e", "."]
25
+ XCTAssertEqual(Transpose.transpose(["Single line."]), expected)
26
+ }
27
+
28
+ func testFirstLineLongerThanSecondLine() {
29
+ let input = ["The fourth line.", "The fifth line."]
30
+ let expected = ["TT", "hh", "ee", "", "ff", "oi", "uf", "rt", "th", "h", " l", "li", "in", "ne", "e.", "."]
31
+ XCTAssertEqual(Transpose.transpose(input), expected)
32
+ }
33
+
34
+ func testSecondLineLongerThanFirstLine() {
35
+ let input = ["The first line.", "The second line."]
36
+ let expected = ["TT", "hh", "ee", "", "fs", "ie", "rc", "so", "tn", " d", "l", "il", "ni", "en", ".e", " ."]
37
+ XCTAssertEqual(Transpose.transpose(input), expected)
38
+ }
39
+
40
+ func testSquare() {
41
+ let input = ["HEART", "EMBER", "ABUSE", "RESIN", "TREND"]
42
+ let expected = ["HEART", "EMBER", "ABUSE", "RESIN", "TREND"]
43
+ XCTAssertEqual(Transpose.transpose(input), expected)
44
+ }
45
+
46
+ func testRectangle() {
47
+ let input = ["FRACTURE", "OUTLINED", "BLOOMING", "SEPTETTE"]
48
+ let expected = ["FOBS", "RULE", "ATOP", "CLOT", "TIME", "UNIT", "RENT", "EDGE"]
49
+ XCTAssertEqual(Transpose.transpose(input), expected)
50
+ }
51
+
52
+ func testTriangle() {
53
+ let input = ["T", "EE", "AAA", "SSSS", "EEEEE", "RRRRRR"]
54
+ let expected = ["TEASER", " EASER", " ASER", " SER", " ER", " R"]
55
+ XCTAssertEqual(Transpose.transpose(input), expected)
56
+ }
57
+
58
+ func testManyLines() {
59
+ let input = [
60
+ "Chor. Two households, both alike in dignity,",
61
+ "In fair Verona, where we lay our scene,",
62
+ "From ancient grudge break to new mutiny,",
63
+ "Where civil blood makes civil hands unclean.",
64
+ "From forth the fatal loins of these two foes",
65
+ "A pair of star-cross'd lovers take their life;",
66
+ "Whose misadventur'd piteous overthrows",
67
+ "Doth with their death bury their parents' strife.",
68
+ "The fearful passage of their death-mark'd love,",
69
+ "And the continuance of their parents' rage,",
70
+ "Which, but their children's end, naught could remove,",
71
+ "Is now the two hours' traffic of our stage;",
72
+ "The which if you with patient ears attend,",
73
+ "What here shall miss, our toil shall strive to mend."
74
+ ]
75
+
76
+ let expected = [
77
+ "CIFWFAWDTAWITW",
78
+ "hnrhr hohnhshh",
79
+ "o oeopotedi ea",
80
+ "rfmrmash cn t",
81
+ ".a e ie fthow",
82
+ " ia fr weh,whh",
83
+ "Trnco miae ie",
84
+ "w ciroitr btcr",
85
+ "oVivtfshfcuhhe",
86
+ " eeih a uote",
87
+ "hrnl sdtln is",
88
+ "oot ttvh tttfh",
89
+ "un bhaeepihw a",
90
+ "saglernianeoyl",
91
+ "e,ro -trsui ol",
92
+ "h uofcu sarhu",
93
+ "owddarrdan o m",
94
+ "lhg to'egccuwi",
95
+ "deemasdaeehris",
96
+ "sr als t ists",
97
+ ",ebk 'phool'h,",
98
+ " reldi ffd",
99
+ "bweso tb rtpo",
100
+ "oea ileutterau",
101
+ "t kcnoorhhnatr",
102
+ "hl isvuyee'fi",
103
+ " atv es iisfet",
104
+ "ayoior trr ino",
105
+ "l lfsoh ecti",
106
+ "ion vedpn l",
107
+ "kuehtteieadoe",
108
+ "erwaharrar,fas",
109
+ " nekt te rh",
110
+ "ismdsehphnnosa",
111
+ "ncuse ra-tau l",
112
+ " et tormsural",
113
+ "dniuthwea'g t",
114
+ "iennwesnr hsts",
115
+ "g,ycoi tkrttet",
116
+ "n ,l r s'a anr",
117
+ "i ef 'dgcgdi",
118
+ "t aol eoe,v",
119
+ "y nei sl,u; e",
120
+ ", .sf to l",
121
+ " e rv d t",
122
+ " ; ie o",
123
+ " f, r",
124
+ " e e m",
125
+ " . m e",
126
+ " o n",
127
+ " v d",
128
+ " e .",
129
+ " ,"
130
+ ]
131
+
132
+ XCTAssertEqual(Transpose.transpose(input), expected)
133
+ }
134
+
135
+ }
@@ -127,6 +127,8 @@
127
127
  E90D62081C653ADC00C266D3 /* PalindromeProductsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90D62071C653ADC00C266D3 /* PalindromeProductsTest.swift */; };
128
128
  E90DE39C1D3E812300F3B881 /* AllYourBaseExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90DE39B1D3E812300F3B881 /* AllYourBaseExample.swift */; };
129
129
  E90DE39E1D3E818000F3B881 /* AllYourBaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90DE39D1D3E818000F3B881 /* AllYourBaseTest.swift */; };
130
+ E9443F251DF5C02700A468B7 /* TransposeExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9443F241DF5C02700A468B7 /* TransposeExample.swift */; };
131
+ E9443F271DF5C04000A468B7 /* TransposeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9443F261DF5C04000A468B7 /* TransposeTest.swift */; };
130
132
  E94BDECF1C510E68009318BB /* BinarySearchExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94BDECD1C510E68009318BB /* BinarySearchExample.swift */; };
131
133
  E94BDED01C510E68009318BB /* BinarySearchTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94BDECE1C510E68009318BB /* BinarySearchTest.swift */; };
132
134
  E951B6BD1D466045009EB5B6 /* BracketPushExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E951B6BC1D466045009EB5B6 /* BracketPushExample.swift */; };
@@ -285,6 +287,8 @@
285
287
  E90D62071C653ADC00C266D3 /* PalindromeProductsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = PalindromeProductsTest.swift; path = "palindrome-products/PalindromeProductsTest.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
286
288
  E90DE39B1D3E812300F3B881 /* AllYourBaseExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AllYourBaseExample.swift; path = "../all-your-base/AllYourBaseExample.swift"; sourceTree = "<group>"; };
287
289
  E90DE39D1D3E818000F3B881 /* AllYourBaseTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AllYourBaseTest.swift; path = "../all-your-base/AllYourBaseTest.swift"; sourceTree = "<group>"; };
290
+ E9443F241DF5C02700A468B7 /* TransposeExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TransposeExample.swift; path = ../transpose/TransposeExample.swift; sourceTree = "<group>"; };
291
+ E9443F261DF5C04000A468B7 /* TransposeTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TransposeTest.swift; path = ../transpose/TransposeTest.swift; sourceTree = "<group>"; };
288
292
  E94BDECD1C510E68009318BB /* BinarySearchExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchExample.swift; path = "binary-search/BinarySearchExample.swift"; sourceTree = "<group>"; };
289
293
  E94BDECE1C510E68009318BB /* BinarySearchTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = BinarySearchTest.swift; path = "binary-search/BinarySearchTest.swift"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
290
294
  E951B6BC1D466045009EB5B6 /* BracketPushExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BracketPushExample.swift; path = "../bracket-push/BracketPushExample.swift"; sourceTree = "<group>"; };
@@ -397,6 +401,7 @@
397
401
  1E9A63701C506EFC00E28AE1 /* strain */,
398
402
  1E9A63731C506EFC00E28AE1 /* sum-of-multiples */,
399
403
  1E9A63761C506EFC00E28AE1 /* tournament */,
404
+ E9443F201DF5BFBF00A468B7 /* transpose */,
400
405
  1E9A63791C506EFC00E28AE1 /* triangle */,
401
406
  1E9A637C1C506EFC00E28AE1 /* trinary */,
402
407
  1E9A637F1C506EFC00E28AE1 /* twelve-days */,
@@ -983,6 +988,16 @@
983
988
  path = acronym;
984
989
  sourceTree = "<group>";
985
990
  };
991
+ E9443F201DF5BFBF00A468B7 /* transpose */ = {
992
+ isa = PBXGroup;
993
+ children = (
994
+ E9443F241DF5C02700A468B7 /* TransposeExample.swift */,
995
+ E9443F261DF5C04000A468B7 /* TransposeTest.swift */,
996
+ );
997
+ name = transpose;
998
+ path = tournament;
999
+ sourceTree = "<group>";
1000
+ };
986
1001
  E94BDECB1C510DF4009318BB /* binary-search */ = {
987
1002
  isa = PBXGroup;
988
1003
  children = (
@@ -1288,12 +1303,14 @@
1288
1303
  E9AFA17A1C614DA0006AD72D /* HouseTest.swift in Sources */,
1289
1304
  1E9A63B11C506EFD00E28AE1 /* LinkedListTest.swift in Sources */,
1290
1305
  1E9A63921C506EFD00E28AE1 /* BinaryExample.swift in Sources */,
1306
+ E9443F271DF5C04000A468B7 /* TransposeTest.swift in Sources */,
1291
1307
  1E9A638F1C506EFD00E28AE1 /* AnagramTest.swift in Sources */,
1292
1308
  1E9A63D51C506EFD00E28AE1 /* SecretHandshakeTest.swift in Sources */,
1293
1309
  1E9A63BA1C506EFD00E28AE1 /* OctalExample.swift in Sources */,
1294
1310
  1E9A63C81C506EFD00E28AE1 /* RaindropsExample.swift in Sources */,
1295
1311
  E951B6BF1D466058009EB5B6 /* BracketPushTest.swift in Sources */,
1296
1312
  E9AFA1601C5BFC57006AD72D /* LargestSeriesProductExample.swift in Sources */,
1313
+ E9443F251DF5C02700A468B7 /* TransposeExample.swift in Sources */,
1297
1314
  E9AFA16D1C5EF4EA006AD72D /* MatrixTest.swift in Sources */,
1298
1315
  1E9A638E1C506EFD00E28AE1 /* AnagramExample.swift in Sources */,
1299
1316
  1E9A63A01C506EFD00E28AE1 /* GigasecondExample.swift in Sources */,
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.3.3
4
+ version: 2.0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katrina Owen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-04 00:00:00.000000000 Z
11
+ date: 2016-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -3207,6 +3207,7 @@ files:
3207
3207
  - tracks/haskell/exercises/pig-latin/src/PigLatin.hs
3208
3208
  - tracks/haskell/exercises/pig-latin/stack.yaml
3209
3209
  - tracks/haskell/exercises/pig-latin/test/Tests.hs
3210
+ - tracks/haskell/exercises/pov/.dummylink
3210
3211
  - tracks/haskell/exercises/pov/examples/success-standard/package.yaml
3211
3212
  - tracks/haskell/exercises/pov/examples/success-standard/src/POV.hs
3212
3213
  - tracks/haskell/exercises/pov/package.yaml
@@ -4946,6 +4947,7 @@ files:
4946
4947
  - tracks/ocaml/tools/test-generator/templates/hamming/template.ml
4947
4948
  - tracks/ocaml/tools/test-generator/templates/hello-world/template.ml
4948
4949
  - tracks/ocaml/tools/test-generator/templates/leap/template.ml
4950
+ - tracks/ocaml/tools/test-generator/templates/minesweeper/template.ml
4949
4951
  - tracks/ocaml/tools/test-generator/templates/raindrops/template.ml
4950
4952
  - tracks/ocaml/tools/test-generator/templates/say/template.ml
4951
4953
  - tracks/ocaml/tools/test-generator/templates/word-count/template.ml
@@ -6319,6 +6321,7 @@ files:
6319
6321
  - tracks/scala/exercises/forth/src/main/scala/.keep
6320
6322
  - tracks/scala/exercises/forth/src/main/scala/ForthEvaluator.scala
6321
6323
  - tracks/scala/exercises/forth/src/test/scala/ForthTest.scala
6324
+ - tracks/scala/exercises/gigasecond/HINTS.md
6322
6325
  - tracks/scala/exercises/gigasecond/build.sbt
6323
6326
  - tracks/scala/exercises/gigasecond/example.scala
6324
6327
  - tracks/scala/exercises/gigasecond/src/main/scala/.keep
@@ -6456,6 +6459,7 @@ files:
6456
6459
  - tracks/scala/exercises/robot-simulator/example.scala
6457
6460
  - tracks/scala/exercises/robot-simulator/src/main/scala/.keep
6458
6461
  - tracks/scala/exercises/robot-simulator/src/test/scala/RobotTest.scala
6462
+ - tracks/scala/exercises/roman-numerals/HINTS.md
6459
6463
  - tracks/scala/exercises/roman-numerals/build.sbt
6460
6464
  - tracks/scala/exercises/roman-numerals/example.scala
6461
6465
  - tracks/scala/exercises/roman-numerals/src/main/scala/.keep
@@ -6766,6 +6770,8 @@ files:
6766
6770
  - tracks/swift/exercises/sum-of-multiples/SumOfMultiplesTest.swift
6767
6771
  - tracks/swift/exercises/tournament/TournamentExample.swift
6768
6772
  - tracks/swift/exercises/tournament/TournamentTest.swift
6773
+ - tracks/swift/exercises/transpose/TransposeExample.swift
6774
+ - tracks/swift/exercises/transpose/TransposeTest.swift
6769
6775
  - tracks/swift/exercises/triangle/TriangleExample.swift
6770
6776
  - tracks/swift/exercises/triangle/TriangleTest.swift
6771
6777
  - tracks/swift/exercises/trinary/TrinaryExample.swift
@@ -1 +0,0 @@
1
- tracks/haskell/exercises/pov/../../common/stack.yaml