trackler 2.0.3.4 → 2.0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/all-your-base/canonical-data.json +21 -21
  3. data/common/exercises/wordy/description.md +24 -38
  4. data/common/exercises/wordy/metadata.yml +1 -1
  5. data/lib/trackler/version.rb +1 -1
  6. data/tracks/c/config.json +10 -0
  7. data/tracks/c/exercises/meetup/makefile +15 -0
  8. data/tracks/c/exercises/meetup/src/example.c +139 -0
  9. data/tracks/c/exercises/meetup/src/example.h +7 -0
  10. data/tracks/c/exercises/meetup/test/test_meetup.c +223 -0
  11. data/tracks/c/exercises/meetup/test/vendor/unity.c +1300 -0
  12. data/tracks/c/exercises/meetup/test/vendor/unity.h +274 -0
  13. data/tracks/c/exercises/meetup/test/vendor/unity_internals.h +701 -0
  14. data/tracks/crystal/config.json +12 -0
  15. data/tracks/crystal/exercises/pascals-triangle/spec/pascals_triangle_spec.cr +30 -0
  16. data/tracks/crystal/exercises/pascals-triangle/src/example.cr +19 -0
  17. data/tracks/crystal/exercises/pascals-triangle/src/pascals_triangle.cr +1 -0
  18. data/tracks/crystal/exercises/run-length-encoding/spec/run_length_encoding_spec.cr +36 -0
  19. data/tracks/crystal/exercises/run-length-encoding/src/example.cr +40 -0
  20. data/tracks/crystal/src/generator/exercises/pascals-triangle.cr +58 -0
  21. data/tracks/crystal/src/generator/exercises/run_length_encoding.cr +42 -0
  22. data/tracks/javascript/config.json +8 -1
  23. data/tracks/javascript/exercises/all-your-base/all-your-base.spec.js +141 -0
  24. data/tracks/javascript/exercises/all-your-base/example.js +59 -0
  25. data/tracks/javascript/exercises/word-count/example.js +5 -5
  26. data/tracks/javascript/exercises/word-count/word-count.spec.js +23 -8
  27. data/tracks/lua/SETUP.md +60 -7
  28. data/tracks/lua/config.json +9 -0
  29. data/tracks/lua/exercises/say/example.lua +4 -4
  30. data/tracks/lua/exercises/variable-length-quantity/example.lua +36 -0
  31. data/tracks/lua/exercises/variable-length-quantity/variable-length-quantity_spec.lua +73 -0
  32. data/tracks/objective-c/.travis.yml +1 -0
  33. data/tracks/objective-c/config.json +8 -0
  34. data/tracks/objective-c/docs/TESTS.md +1 -1
  35. data/tracks/objective-c/exercises/transpose/TransposeExample.h +7 -0
  36. data/tracks/objective-c/exercises/transpose/TransposeExample.m +59 -0
  37. data/tracks/objective-c/exercises/transpose/TransposeTest.m +150 -0
  38. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
  39. data/tracks/ocaml/.gitignore +1 -0
  40. data/tracks/ocaml/tools/test-generator/Makefile +3 -0
  41. data/tracks/ocaml/tools/test-generator/src/controller.ml +11 -16
  42. data/tracks/ocaml/tools/test-generator/src/model.ml +4 -0
  43. data/tracks/ocaml/tools/test-generator/src/parser.ml +8 -1
  44. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +5 -0
  45. data/tracks/ocaml/tools/test-generator/templates/all-your-base/template.ml +16 -0
  46. data/tracks/ocaml/tools/test-generator/test/model_test.ml +2 -0
  47. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +8 -0
  48. data/tracks/perl5/docs/RESOURCES.md +57 -0
  49. data/tracks/perl5/exercises/hamming/Example.pm +7 -0
  50. data/tracks/perl5/exercises/hamming/hamming.t +17 -4
  51. data/tracks/perl5/exercises/rna-transcription/rna.t +4 -4
  52. data/tracks/perl6/.gitignore +2 -0
  53. data/tracks/perl6/config.json +5 -0
  54. data/tracks/perl6/exercises/phone-number/Example.pm +30 -0
  55. data/tracks/perl6/exercises/phone-number/cases.json +47 -0
  56. data/tracks/perl6/exercises/phone-number/phone.t +48 -0
  57. data/tracks/purescript/.gitignore +8 -0
  58. data/tracks/purescript/config.json +8 -3
  59. data/tracks/purescript/exercises/hello-world/bower.json +17 -0
  60. data/tracks/purescript/exercises/hello-world/examples/src/HelloWorld.purs +8 -0
  61. data/tracks/purescript/exercises/hello-world/src/HelloWorld.purs +6 -0
  62. data/tracks/purescript/exercises/hello-world/test/Main.purs +18 -0
  63. data/tracks/scala/exercises/leap/HINTS.md +4 -0
  64. data/tracks/scala/exercises/robot-name/HINTS.md +5 -0
  65. data/tracks/swift/docs/INSTALLATION.md +4 -1
  66. data/tracks/swift/exercises/accumulate/AccumulateTest.swift +1 -1
  67. data/tracks/swift/exercises/binary/BinaryExample.swift +4 -1
  68. data/tracks/swift/exercises/crypto-square/CryptoSquareExample.swift +3 -2
  69. data/tracks/swift/exercises/leap/LeapExample.swift +1 -3
  70. data/tracks/swift/exercises/pascals-triangle/PascalsTriangleTest.swift +1 -1
  71. data/tracks/swift/exercises/poker/PokerExample.swift +3 -3
  72. data/tracks/swift/exercises/poker/PokerTest.swift +38 -38
  73. data/tracks/swift/exercises/saddle-points/SaddlePointsTest.swift +1 -1
  74. data/tracks/swift/exercises/scrabble-score/ScrabbleScoreExample.swift +6 -3
  75. data/tracks/swift/exercises/series/SeriesTest.swift +1 -1
  76. data/tracks/swift/exercises/simple-linked-list/SimpleLinkedListExample.swift +2 -2
  77. data/tracks/swift/exercises/space-age/SpaceAgeExample.swift +10 -12
  78. data/tracks/swift/exercises/strain/StrainTest.swift +1 -1
  79. data/tracks/swift/exercises/tournament/TournamentExample.swift +2 -2
  80. data/tracks/swift/exercises/triangle/TriangleExample.swift +7 -3
  81. data/tracks/swift/exercises/wordy/WordyExample.swift +1 -2
  82. metadata +34 -3
  83. data/tracks/purescript/exercises/.keep +0 -0
@@ -4,15 +4,15 @@ function Words() {}
4
4
 
5
5
  Words.prototype.count = function (input) {
6
6
  var counts = {};
7
- var words = input.match(/\S+/g);
7
+ var words = input.toLowerCase()
8
+ .replace(/[,."\/!&@$%\^\*;:{}()¡¿?]/g, ' ')
9
+ .replace(/\s'(\w+)'\s/, ' '+'$1'+' ')
10
+ .match(/\S+/g);
8
11
 
9
12
  words.forEach(function (word) {
10
- var lcWord = word.toLowerCase();
11
- counts[lcWord] = counts.hasOwnProperty(lcWord) ? counts[lcWord] + 1 : 1;
13
+ counts[word] = counts.hasOwnProperty(word) ? counts[word] + 1 : 1;
12
14
  });
13
-
14
15
  return counts;
15
16
  };
16
17
 
17
18
  module.exports = Words;
18
-
@@ -8,19 +8,24 @@ describe('count()', function() {
8
8
  expect(words.count('word')).toEqual(expectedCounts);
9
9
  });
10
10
 
11
- xit('counts one of each', function() {
11
+ xit('counts one of each word', function() {
12
12
  var expectedCounts = { one: 1, of: 1, each: 1 };
13
13
  expect(words.count('one of each')).toEqual(expectedCounts);
14
14
  });
15
15
 
16
- xit('counts multiple occurrences', function() {
16
+ xit('counts multiple occurrences of a word', function() {
17
17
  var expectedCounts = { one: 1, fish: 4, two: 1, red: 1, blue: 1 };
18
18
  expect(words.count('one fish two fish red fish blue fish')).toEqual(expectedCounts);
19
19
  });
20
20
 
21
- xit('includes punctuation', function() {
22
- var expectedCounts = { car: 1, ':': 2, carpet: 1, as: 1, java: 1, 'javascript!!&@$%^&': 1 };
23
- expect(words.count('car : carpet as java : javascript!!&@$%^&')).toEqual(expectedCounts);
21
+ xit('handles cramped lists', function() {
22
+ var expectedCounts = { one: 1, two: 1, three: 1 };
23
+ expect(words.count('one,two,three')).toEqual(expectedCounts);
24
+ });
25
+
26
+ xit('ignores punctuation', function() {
27
+ var expectedCounts = { car: 1, carpet: 1, as: 1, java: 1, javascript: 1 };
28
+ expect(words.count('car : carpet as java: javascript!!&@$%^&')).toEqual(expectedCounts);
24
29
  });
25
30
 
26
31
  xit('includes numbers', function() {
@@ -33,8 +38,18 @@ describe('count()', function() {
33
38
  expect(words.count('go Go GO')).toEqual(expectedCounts);
34
39
  });
35
40
 
41
+ xit('counts words with apostrophes', function() {
42
+ var expectedCounts = { 'first': 1, 'don\'t': 2, 'laugh': 1, 'then': 1, 'cry': 1 };
43
+ expect(words.count('First: don\'t laugh. Then: don\'t cry.')).toEqual(expectedCounts);
44
+ });
45
+
46
+ xit('counts words with quotations', function() {
47
+ var expectedCounts = { 'joe': 1, 'can\'t': 1, 'tell': 1, 'between': 1, 'large': 2, 'and': 1 };
48
+ expect(words.count('Joe can\'t tell between \'large\' and large.')).toEqual(expectedCounts);
49
+ });
50
+
36
51
  xit('counts properly international characters', function() {
37
- var expectedCounts = { '¡hola!': 1, '¿qué': 1, 'tal?': 1, 'привет!': 1 };
52
+ var expectedCounts = { 'hola': 1, 'qué': 1, 'tal': 1, 'привет': 1 };
38
53
  expect(words.count('¡Hola! ¿Qué tal? Привет!')).toEqual(expectedCounts);
39
54
  });
40
55
 
@@ -43,7 +58,7 @@ describe('count()', function() {
43
58
  expect(words.count('hello\nworld')).toEqual(expectedCounts);
44
59
  });
45
60
 
46
- xit('counts tabs', function() {
61
+ xit('counts tabs as white space', function() {
47
62
  var expectedCounts = { hello: 1, world: 1 };
48
63
  expect(words.count('hello\tworld')).toEqual(expectedCounts);
49
64
  });
@@ -59,7 +74,7 @@ describe('count()', function() {
59
74
  });
60
75
 
61
76
  xit('handles properties that exist on Object’s prototype', function() {
62
- var expectedCounts = { reserved: 1, words: 1, like: 1, constructor: 1, and: 1, tostring: 1, 'ok?': 1 };
77
+ var expectedCounts = { reserved: 1, words: 1, like: 1, constructor: 1, and: 1, tostring: 1, ok: 1 };
63
78
  expect(words.count('reserved words like constructor and toString ok?')).toEqual(expectedCounts);
64
79
  });
65
80
  });
data/tracks/lua/SETUP.md CHANGED
@@ -1,17 +1,68 @@
1
1
  ### Getting started
2
- First install lua and [luarocks][2] using [homebrew][1]
2
+ #### MacOS
3
+ First install Lua and [Luarocks][2] using [Homebrew][1]:
3
4
 
4
- $ brew install lua
5
+ ```shell
6
+ $ brew install lua
7
+ ```
5
8
 
6
- Then install [busted][3] testing framework for lua
9
+ Then install the [Busted][3] testing framework for Lua:
7
10
 
8
- $ luarocks install busted
11
+ ```shell
12
+ $ luarocks install busted
13
+ ```
9
14
 
10
- Then run your test
15
+ Then run your tests:
11
16
 
12
- $ busted .
17
+ ```shell
18
+ $ busted .
19
+ ```
13
20
 
14
- Other resources
21
+ #### Ubuntu
22
+ First install Lua and [Luarocks][2] using [Apt][6]:
23
+
24
+ ```shell
25
+ $ sudo apt-get install lua5.3 luarocks
26
+ ```
27
+
28
+ Then install the [Busted][3] testing framework for Lua:
29
+
30
+ ```shell
31
+ $ luarocks install busted
32
+ ```
33
+
34
+ If this fails, you may need to use `sudo`:
35
+
36
+ ```shell
37
+ $ sudo luarocks install busted
38
+ ```
39
+
40
+ Then run your tests:
41
+
42
+ ```shell
43
+ $ busted .
44
+ ```
45
+
46
+ #### Windows
47
+ First install Lua and [Luarocks][2] using [Chocolatey][7]:
48
+
49
+ ```
50
+ C:\> choco install lua
51
+ ```
52
+
53
+ Then install the [Busted][3] testing framework for Lua:
54
+
55
+ ```
56
+ C:\> luarocks install busted
57
+ ```
58
+
59
+ Then run your tests:
60
+
61
+ ```
62
+ C:\> busted .
63
+ ```
64
+
65
+ #### Other resources
15
66
 
16
67
  1. [Lua Style Guide][4]
17
68
  2. [Learn Lua in 15 minutes][5]
@@ -21,3 +72,5 @@ Other resources
21
72
  [3]: http://olivinelabs.com/busted/
22
73
  [4]: https://github.com/Olivine-Labs/lua-style-guide
23
74
  [5]: http://tylerneylon.com/a/learn-lua/
75
+ [6]: https://help.ubuntu.com/lts/serverguide/apt.html
76
+ [7]: http://chocolatey.org/
@@ -54,6 +54,15 @@
54
54
  "topics": [
55
55
  "mathematics"
56
56
  ]
57
+ }, {
58
+ "slug": "variable-length-quantity",
59
+ "difficulty": 6,
60
+ "topics": [
61
+ "control-flow (if-else statements)",
62
+ "control-flow (loops)",
63
+ "bitwise operations",
64
+ "arrays"
65
+ ]
57
66
  }, {
58
67
  "slug": "anagram",
59
68
  "difficulty": 6,
@@ -67,7 +67,7 @@ end
67
67
  return function(n)
68
68
  if n < 0 or n > 999999999999 then return -1 end
69
69
 
70
- local blahs = {}
70
+ local groups = {}
71
71
  local group_index = 0
72
72
 
73
73
  while n > 0 do
@@ -77,16 +77,16 @@ return function(n)
77
77
  if group_name[group_index] then
78
78
  group = group .. ' ' .. group_name[group_index]
79
79
  end
80
- table.insert(blahs, 1, group)
80
+ table.insert(groups, 1, group)
81
81
  end
82
82
 
83
83
  n = n // 1000
84
84
  group_index = group_index + 1
85
85
  end
86
86
 
87
- if #blahs == 0 then
87
+ if #groups == 0 then
88
88
  return 'zero'
89
89
  else
90
- return table.concat(blahs, ' ')
90
+ return table.concat(groups, ' ')
91
91
  end
92
92
  end
@@ -0,0 +1,36 @@
1
+ local function decode(bytes)
2
+ local values = {}
3
+ local n = 0
4
+ for i, byte in ipairs(bytes) do
5
+ n = n << 7
6
+ n = n + (byte & 0x7f)
7
+ if byte & 0x80 == 0 then
8
+ table.insert(values, n)
9
+ n = 0
10
+ end
11
+ assert((i ~= #bytes) or (byte & 0x80 == 0), 'incomplete byte sequence')
12
+ end
13
+ return values
14
+ end
15
+
16
+ local function encode_single(n)
17
+ local bytes = { n & 0x7f }
18
+ n = n >> 7
19
+ while n > 0 do
20
+ table.insert(bytes, 1, n & 0x7f | 0x80)
21
+ n = n >> 7
22
+ end
23
+ return bytes
24
+ end
25
+
26
+ local function encode(values)
27
+ local bytes = {}
28
+ for _, value in ipairs(values) do
29
+ for _, byte in ipairs(encode_single(value)) do
30
+ table.insert(bytes, byte)
31
+ end
32
+ end
33
+ return bytes
34
+ end
35
+
36
+ return { decode = decode, encode = encode }
@@ -0,0 +1,73 @@
1
+ local vlq = require 'variable-length-quantity'
2
+
3
+ describe('variable-length-quantity', function()
4
+ it('should decode single bytes', function()
5
+ assert.are.same({ 0x00 }, vlq.decode({ 0x00 }))
6
+ assert.are.same({ 0x40 }, vlq.decode({ 0x40 }))
7
+ assert.are.same({ 0x7f }, vlq.decode({ 0x7f }))
8
+ end)
9
+
10
+ it('should decode double bytes', function()
11
+ assert.are.same({ 0x80 }, vlq.decode({ 0x81, 0x00 }))
12
+ assert.are.same({ 0x2000 }, vlq.decode({ 0xc0, 0x00 }))
13
+ assert.are.same({ 0x3fff }, vlq.decode({ 0xff, 0x7f }))
14
+ end)
15
+
16
+ it('should decode triple bytes', function()
17
+ assert.are.same({ 0x4000 }, vlq.decode({ 0x81, 0x80, 0x00 }))
18
+ assert.are.same({ 0x100000 }, vlq.decode({ 0xc0, 0x80, 0x00 }))
19
+ assert.are.same({ 0x1fffff }, vlq.decode({ 0xff, 0xff, 0x7f }))
20
+ end)
21
+
22
+ it('should decode quadruple bytes', function()
23
+ assert.are.same({ 0x200000 }, vlq.decode({ 0x81, 0x80, 0x80, 0x00 }))
24
+ assert.are.same({ 0x08000000 }, vlq.decode({ 0xc0, 0x80, 0x80, 0x00 }))
25
+ assert.are.same({ 0x0fffffff }, vlq.decode({ 0xff, 0xff, 0xff, 0x7f }))
26
+ end)
27
+
28
+ it('should decode multiple values', function()
29
+ assert.are.same(
30
+ { 0x2000, 0x123456, 0x0fffffff, 0x00, 0x3fff, 0x4000 },
31
+ vlq.decode({ 0xc0, 0x00, 0xc8, 0xe8, 0x56, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0x81, 0x80, 0x00 })
32
+ )
33
+ end)
34
+
35
+ it('should encode single bytes', function()
36
+ assert.are.same({ 0x00 }, vlq.encode({ 0x00 }))
37
+ assert.are.same({ 0x40 }, vlq.encode({ 0x40 }))
38
+ assert.are.same({ 0x7f }, vlq.encode({ 0x7f }))
39
+ end)
40
+
41
+ it('should encode double bytes', function()
42
+ assert.are.same({ 0x81, 0x00 }, vlq.encode({ 0x80 }))
43
+ assert.are.same({ 0xc0, 0x00 }, vlq.encode({ 0x2000 }))
44
+ assert.are.same({ 0xff, 0x7f }, vlq.encode({ 0x3fff }))
45
+ end)
46
+
47
+ it('should encode triple bytes', function()
48
+ assert.are.same({ 0x81, 0x80, 0x00 }, vlq.encode({ 0x4000 }))
49
+ assert.are.same({ 0xc0, 0x80, 0x00 }, vlq.encode({ 0x100000 }))
50
+ assert.are.same({ 0xff, 0xff, 0x7f }, vlq.encode({ 0x1fffff }))
51
+ end)
52
+
53
+ it('should encode quadruple bytes', function()
54
+ assert.are.same({ 0x81, 0x80, 0x80, 0x00 }, vlq.encode({ 0x200000 }))
55
+ assert.are.same({ 0xc0, 0x80, 0x80, 0x00 }, vlq.encode({ 0x08000000 }))
56
+ assert.are.same({ 0xff, 0xff, 0xff, 0x7f }, vlq.encode({ 0x0fffffff }))
57
+ end)
58
+
59
+ it('should encode multiple values', function()
60
+ assert.are.same({ 0x40, 0x7f }, vlq.encode({ 0x40, 0x7f }))
61
+ assert.are.same({ 0x81, 0x80, 0x00, 0xc8, 0xe8, 0x56 }, vlq.encode({ 0x4000, 0x123456 }))
62
+ assert.are.same(
63
+ { 0xc0, 0x00, 0xc8, 0xe8, 0x56, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0x81, 0x80, 0x00 },
64
+ vlq.encode({ 0x2000, 0x123456, 0x0fffffff, 0x00, 0x3fff, 0x4000 })
65
+ )
66
+ end)
67
+
68
+ it('should raise an error when decoding an incomplete byte sequence', function()
69
+ assert.has.error(function()
70
+ vlq.decode({ 0x81, 0x00, 0x80 })
71
+ end, 'incomplete byte sequence')
72
+ end)
73
+ end)
@@ -3,6 +3,7 @@ osx_image: xcode7.3
3
3
  xcode_project: 'xcodeProject/ObjectiveC.xcodeproj'
4
4
  xcode_scheme: 'xobjectivecTest'
5
5
  before_install:
6
+ - gem install bundler
6
7
  - gem install danger
7
8
  - brew cask uninstall oclint
8
9
  - brew tap oclint/formulae
@@ -218,6 +218,14 @@
218
218
  "Searching",
219
219
  "Transforming"
220
220
  ]
221
+ },
222
+ {
223
+ "difficulty": 4,
224
+ "slug": "transpose",
225
+ "topics": [
226
+ "Strings",
227
+ "Transforming"
228
+ ]
221
229
  },
222
230
  {
223
231
  "difficulty": 5,
@@ -42,6 +42,6 @@ Run the tests with:
42
42
  $ objc ExerciseName
43
43
  ```
44
44
 
45
- The objc utility uses the exercise name to find the test file, `ExerciseNameTest.m`, the header file, `ExerciseName.h` and source file `ExerciseNameTest.m`. The files are inserted into a temporary Xcode Project and then `xctool` is used to run the tests for the project.
45
+ The objc utility uses the exercise name to find the test file, `ExerciseNameTest.m`, the header file, `ExerciseName.h` and source file `ExerciseName.m`. The files are inserted into a temporary Xcode Project and then `xctool` is used to run the tests for the project.
46
46
 
47
47
  While `objc` makes it so you never have to launch Xcode to complete these exercises, the error messages and feedback through the command-line are not as clear as through the Xcode user interface.
@@ -0,0 +1,7 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ @interface Transpose : NSObject
4
+
5
+ + (NSArray<NSString *> *)transpose:(NSArray<NSString *> *)input;
6
+
7
+ @end
@@ -0,0 +1,59 @@
1
+ #import "TransposeExample.h"
2
+
3
+ @implementation Transpose
4
+
5
+ + (NSArray<NSString *> *)transpose:(NSArray<NSString *> *)input {
6
+ int maxLength = 0;
7
+
8
+ for (NSString *line in input) {
9
+ if (line.length > maxLength) {
10
+ maxLength = (int)line.length;
11
+ }
12
+ }
13
+
14
+ NSMutableArray<NSString *> *result = [NSMutableArray arrayWithCapacity:maxLength];
15
+
16
+ for (int i = 0; i < maxLength; i++) {
17
+ [result addObject:@""];
18
+
19
+ for (NSString *line in input) {
20
+ NSString *character;
21
+
22
+ if (i < line.length) {
23
+ character = [line substringWithRange:NSMakeRange(i, 1)];
24
+ } else {
25
+ character = @" ";
26
+ }
27
+
28
+ result[i] = [result[i] stringByAppendingString:character];
29
+ }
30
+ }
31
+
32
+ NSMutableArray<NSString *> *trimmedResult = [[NSMutableArray alloc] init];
33
+
34
+ for (NSString *line in result) {
35
+ [trimmedResult addObject:[self stringByTrimmingTrailingWhiteSpace:line]];
36
+ }
37
+
38
+ return trimmedResult;
39
+ }
40
+
41
+ + (NSString *)stringByTrimmingTrailingWhiteSpace:(NSString *)string {
42
+ NSUInteger location = 0;
43
+ NSUInteger length = [string length];
44
+ unichar charBuffer[length];
45
+ [string getCharacters:charBuffer];
46
+
47
+ NSCharacterSet *characterSet = [NSCharacterSet whitespaceCharacterSet];
48
+
49
+ while (length > 0) {
50
+ if (![characterSet characterIsMember:charBuffer[length - 1]]) {
51
+ break;
52
+ }
53
+ length--;
54
+ }
55
+
56
+ return [string substringWithRange:NSMakeRange(location, length - location)];
57
+ }
58
+
59
+ @end
@@ -0,0 +1,150 @@
1
+ #import <XCTest/XCTest.h>
2
+
3
+ #if __has_include("TransposeExample.h")
4
+ # import "TransposeExample.h"
5
+ # else
6
+ # import "Transpose.h"
7
+ #endif
8
+
9
+ @interface TransposeTest : XCTestCase
10
+
11
+ @end
12
+
13
+ @implementation TransposeTest
14
+
15
+ - (void)testEmptyInput {
16
+ XCTAssertEqualObjects([Transpose transpose:@[]], @[]);
17
+ }
18
+
19
+ - (void)testTwoCharactersInARow {
20
+ NSArray<NSString *> *input = @[@"A1"];
21
+ NSArray<NSString *> *expected = @[@"A", @"1"];
22
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
23
+ }
24
+
25
+ - (void)testTwoCharactersInAColumn {
26
+ NSArray<NSString *> *input = @[@"A", @"1"];
27
+ NSArray<NSString *> *expected = @[@"A1"];
28
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
29
+ }
30
+
31
+ - (void)testSimple {
32
+ NSArray<NSString *> *input = @[@"ABC", @"123"];
33
+ NSArray<NSString *> *expected = @[@"A1", @"B2", @"C3"];
34
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
35
+ }
36
+
37
+ - (void)testSingleLine {
38
+ NSArray<NSString *> *input = @[@"Single line."];
39
+ NSArray<NSString *> *expected = @[@"S", @"i", @"n", @"g", @"l", @"e", @"", @"l", @"i", @"n", @"e", @"."];
40
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
41
+ }
42
+
43
+ - (void)testFirstLineLongerThanSecondLine {
44
+ NSArray<NSString *> *input = @[@"The fourth line.", @"The fifth line."];
45
+ NSArray<NSString *> *expected = @[@"TT", @"hh", @"ee", @"", @"ff", @"oi", @"uf", @"rt", @"th", @"h", @" l", @"li", @"in", @"ne", @"e.", @"."];
46
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
47
+ }
48
+
49
+ - (void)testSecondLineLongerThanFirstLine {
50
+ NSArray<NSString *> *input = @[@"The first line.", @"The second line."];
51
+ NSArray<NSString *> *expected = @[@"TT", @"hh", @"ee", @"", @"fs", @"ie", @"rc", @"so", @"tn", @" d", @"l", @"il", @"ni", @"en", @".e", @" ."];
52
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
53
+ }
54
+
55
+ - (void)testSquare {
56
+ NSArray<NSString *> *input = @[@"HEART", @"EMBER", @"ABUSE", @"RESIN", @"TREND"];
57
+ NSArray<NSString *> *expected = @[@"HEART", @"EMBER", @"ABUSE", @"RESIN", @"TREND"];
58
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
59
+ }
60
+
61
+ - (void)testRectangle {
62
+ NSArray<NSString *> *input = @[@"FRACTURE", @"OUTLINED", @"BLOOMING", @"SEPTETTE"];
63
+ NSArray<NSString *> *expected = @[@"FOBS", @"RULE", @"ATOP", @"CLOT", @"TIME", @"UNIT", @"RENT", @"EDGE"];
64
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
65
+ }
66
+
67
+ - (void)testTriangle {
68
+ NSArray<NSString *> *input = @[@"T", @"EE", @"AAA", @"SSSS", @"EEEEE", @"RRRRRR"];
69
+ NSArray<NSString *> *expected = @[@"TEASER", @" EASER", @" ASER", @" SER", @" ER", @" R"];
70
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
71
+ }
72
+
73
+ - (void)testManyLines {
74
+ NSArray<NSString *> *input = @[@"Chor. Two households, both alike in dignity,",
75
+ @"In fair Verona, where we lay our scene,",
76
+ @"From ancient grudge break to new mutiny,",
77
+ @"Where civil blood makes civil hands unclean.",
78
+ @"From forth the fatal loins of these two foes",
79
+ @"A pair of star-cross'd lovers take their life;",
80
+ @"Whose misadventur'd piteous overthrows",
81
+ @"Doth with their death bury their parents' strife.",
82
+ @"The fearful passage of their death-mark'd love,",
83
+ @"And the continuance of their parents' rage,",
84
+ @"Which, but their children's end, naught could remove,",
85
+ @"Is now the two hours' traffic of our stage;",
86
+ @"The which if you with patient ears attend,",
87
+ @"What here shall miss, our toil shall strive to mend."
88
+ ];
89
+
90
+ NSArray<NSString *> *expected = @[
91
+ @"CIFWFAWDTAWITW",
92
+ @"hnrhr hohnhshh",
93
+ @"o oeopotedi ea",
94
+ @"rfmrmash cn t",
95
+ @".a e ie fthow",
96
+ @" ia fr weh,whh",
97
+ @"Trnco miae ie",
98
+ @"w ciroitr btcr",
99
+ @"oVivtfshfcuhhe",
100
+ @" eeih a uote",
101
+ @"hrnl sdtln is",
102
+ @"oot ttvh tttfh",
103
+ @"un bhaeepihw a",
104
+ @"saglernianeoyl",
105
+ @"e,ro -trsui ol",
106
+ @"h uofcu sarhu",
107
+ @"owddarrdan o m",
108
+ @"lhg to'egccuwi",
109
+ @"deemasdaeehris",
110
+ @"sr als t ists",
111
+ @",ebk 'phool'h,",
112
+ @" reldi ffd",
113
+ @"bweso tb rtpo",
114
+ @"oea ileutterau",
115
+ @"t kcnoorhhnatr",
116
+ @"hl isvuyee'fi",
117
+ @" atv es iisfet",
118
+ @"ayoior trr ino",
119
+ @"l lfsoh ecti",
120
+ @"ion vedpn l",
121
+ @"kuehtteieadoe",
122
+ @"erwaharrar,fas",
123
+ @" nekt te rh",
124
+ @"ismdsehphnnosa",
125
+ @"ncuse ra-tau l",
126
+ @" et tormsural",
127
+ @"dniuthwea'g t",
128
+ @"iennwesnr hsts",
129
+ @"g,ycoi tkrttet",
130
+ @"n ,l r s'a anr",
131
+ @"i ef 'dgcgdi",
132
+ @"t aol eoe,v",
133
+ @"y nei sl,u; e",
134
+ @", .sf to l",
135
+ @" e rv d t",
136
+ @" ; ie o",
137
+ @" f, r",
138
+ @" e e m",
139
+ @" . m e",
140
+ @" o n",
141
+ @" v d",
142
+ @" e .",
143
+ @" ,"
144
+ ];
145
+
146
+ XCTAssertEqualObjects([Transpose transpose:input], expected);
147
+ }
148
+
149
+
150
+ @end