trackler 2.0.3.4 → 2.0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/common/exercises/all-your-base/canonical-data.json +21 -21
- data/common/exercises/wordy/description.md +24 -38
- data/common/exercises/wordy/metadata.yml +1 -1
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +10 -0
- data/tracks/c/exercises/meetup/makefile +15 -0
- data/tracks/c/exercises/meetup/src/example.c +139 -0
- data/tracks/c/exercises/meetup/src/example.h +7 -0
- data/tracks/c/exercises/meetup/test/test_meetup.c +223 -0
- data/tracks/c/exercises/meetup/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/meetup/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/meetup/test/vendor/unity_internals.h +701 -0
- data/tracks/crystal/config.json +12 -0
- data/tracks/crystal/exercises/pascals-triangle/spec/pascals_triangle_spec.cr +30 -0
- data/tracks/crystal/exercises/pascals-triangle/src/example.cr +19 -0
- data/tracks/crystal/exercises/pascals-triangle/src/pascals_triangle.cr +1 -0
- data/tracks/crystal/exercises/run-length-encoding/spec/run_length_encoding_spec.cr +36 -0
- data/tracks/crystal/exercises/run-length-encoding/src/example.cr +40 -0
- data/tracks/crystal/src/generator/exercises/pascals-triangle.cr +58 -0
- data/tracks/crystal/src/generator/exercises/run_length_encoding.cr +42 -0
- data/tracks/javascript/config.json +8 -1
- data/tracks/javascript/exercises/all-your-base/all-your-base.spec.js +141 -0
- data/tracks/javascript/exercises/all-your-base/example.js +59 -0
- data/tracks/javascript/exercises/word-count/example.js +5 -5
- data/tracks/javascript/exercises/word-count/word-count.spec.js +23 -8
- data/tracks/lua/SETUP.md +60 -7
- data/tracks/lua/config.json +9 -0
- data/tracks/lua/exercises/say/example.lua +4 -4
- data/tracks/lua/exercises/variable-length-quantity/example.lua +36 -0
- data/tracks/lua/exercises/variable-length-quantity/variable-length-quantity_spec.lua +73 -0
- data/tracks/objective-c/.travis.yml +1 -0
- data/tracks/objective-c/config.json +8 -0
- data/tracks/objective-c/docs/TESTS.md +1 -1
- data/tracks/objective-c/exercises/transpose/TransposeExample.h +7 -0
- data/tracks/objective-c/exercises/transpose/TransposeExample.m +59 -0
- data/tracks/objective-c/exercises/transpose/TransposeTest.m +150 -0
- data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
- data/tracks/ocaml/.gitignore +1 -0
- data/tracks/ocaml/tools/test-generator/Makefile +3 -0
- data/tracks/ocaml/tools/test-generator/src/controller.ml +11 -16
- data/tracks/ocaml/tools/test-generator/src/model.ml +4 -0
- data/tracks/ocaml/tools/test-generator/src/parser.ml +8 -1
- data/tracks/ocaml/tools/test-generator/src/special_cases.ml +5 -0
- data/tracks/ocaml/tools/test-generator/templates/all-your-base/template.ml +16 -0
- data/tracks/ocaml/tools/test-generator/test/model_test.ml +2 -0
- data/tracks/ocaml/tools/test-generator/test/parser_test.ml +8 -0
- data/tracks/perl5/docs/RESOURCES.md +57 -0
- data/tracks/perl5/exercises/hamming/Example.pm +7 -0
- data/tracks/perl5/exercises/hamming/hamming.t +17 -4
- data/tracks/perl5/exercises/rna-transcription/rna.t +4 -4
- data/tracks/perl6/.gitignore +2 -0
- data/tracks/perl6/config.json +5 -0
- data/tracks/perl6/exercises/phone-number/Example.pm +30 -0
- data/tracks/perl6/exercises/phone-number/cases.json +47 -0
- data/tracks/perl6/exercises/phone-number/phone.t +48 -0
- data/tracks/purescript/.gitignore +8 -0
- data/tracks/purescript/config.json +8 -3
- data/tracks/purescript/exercises/hello-world/bower.json +17 -0
- data/tracks/purescript/exercises/hello-world/examples/src/HelloWorld.purs +8 -0
- data/tracks/purescript/exercises/hello-world/src/HelloWorld.purs +6 -0
- data/tracks/purescript/exercises/hello-world/test/Main.purs +18 -0
- data/tracks/scala/exercises/leap/HINTS.md +4 -0
- data/tracks/scala/exercises/robot-name/HINTS.md +5 -0
- data/tracks/swift/docs/INSTALLATION.md +4 -1
- data/tracks/swift/exercises/accumulate/AccumulateTest.swift +1 -1
- data/tracks/swift/exercises/binary/BinaryExample.swift +4 -1
- data/tracks/swift/exercises/crypto-square/CryptoSquareExample.swift +3 -2
- data/tracks/swift/exercises/leap/LeapExample.swift +1 -3
- data/tracks/swift/exercises/pascals-triangle/PascalsTriangleTest.swift +1 -1
- data/tracks/swift/exercises/poker/PokerExample.swift +3 -3
- data/tracks/swift/exercises/poker/PokerTest.swift +38 -38
- data/tracks/swift/exercises/saddle-points/SaddlePointsTest.swift +1 -1
- data/tracks/swift/exercises/scrabble-score/ScrabbleScoreExample.swift +6 -3
- data/tracks/swift/exercises/series/SeriesTest.swift +1 -1
- data/tracks/swift/exercises/simple-linked-list/SimpleLinkedListExample.swift +2 -2
- data/tracks/swift/exercises/space-age/SpaceAgeExample.swift +10 -12
- data/tracks/swift/exercises/strain/StrainTest.swift +1 -1
- data/tracks/swift/exercises/tournament/TournamentExample.swift +2 -2
- data/tracks/swift/exercises/triangle/TriangleExample.swift +7 -3
- data/tracks/swift/exercises/wordy/WordyExample.swift +1 -2
- metadata +34 -3
- 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.
|
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
|
-
|
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('
|
22
|
-
var expectedCounts = {
|
23
|
-
expect(words.count('
|
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 = { '
|
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,
|
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
|
-
|
2
|
+
#### MacOS
|
3
|
+
First install Lua and [Luarocks][2] using [Homebrew][1]:
|
3
4
|
|
4
|
-
|
5
|
+
```shell
|
6
|
+
$ brew install lua
|
7
|
+
```
|
5
8
|
|
6
|
-
Then install [
|
9
|
+
Then install the [Busted][3] testing framework for Lua:
|
7
10
|
|
8
|
-
|
11
|
+
```shell
|
12
|
+
$ luarocks install busted
|
13
|
+
```
|
9
14
|
|
10
|
-
Then run your
|
15
|
+
Then run your tests:
|
11
16
|
|
12
|
-
|
17
|
+
```shell
|
18
|
+
$ busted .
|
19
|
+
```
|
13
20
|
|
14
|
-
|
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/
|
data/tracks/lua/config.json
CHANGED
@@ -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
|
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(
|
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 #
|
87
|
+
if #groups == 0 then
|
88
88
|
return 'zero'
|
89
89
|
else
|
90
|
-
return table.concat(
|
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)
|
@@ -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 `
|
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,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
|