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.
- 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
|