trackler 2.2.0.0 → 2.2.0.1
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/lib/trackler/version.rb +1 -1
- data/problem-specifications/CONTRIBUTING.md +1 -1
- data/tracks/bash/.travis.yml +1 -1
- data/tracks/bash/config.json +30 -3
- data/tracks/c/README.md +1 -1
- data/tracks/c/config.json +131 -39
- data/tracks/ceylon/README.md +6 -6
- data/tracks/ceylon/config.json +21 -3
- data/tracks/chapel/.travis.yml +1 -1
- data/tracks/clojurescript/.travis.yml +1 -1
- data/tracks/clojurescript/README.md +6 -6
- data/tracks/clojurescript/exercises/.keep +0 -0
- data/tracks/coffeescript/.travis.yml +1 -1
- data/tracks/coldfusion/.travis.yml +1 -1
- data/tracks/coq/.travis.yml +1 -1
- data/tracks/cpp/CMakeLists.txt +1 -0
- data/tracks/cpp/README.md +1 -1
- data/tracks/cpp/config.json +8 -0
- data/tracks/cpp/exercises/atbash-cipher/CMakeLists.txt +52 -0
- data/tracks/cpp/exercises/atbash-cipher/atbash_cipher_test.cpp +68 -0
- data/tracks/cpp/exercises/atbash-cipher/example.cpp +54 -0
- data/tracks/cpp/exercises/atbash-cipher/example.h +13 -0
- data/tracks/csharp/config.json +315 -6
- data/tracks/d/.travis.yml +1 -1
- data/tracks/dart/README.md +2 -2
- data/tracks/dart/config.json +21 -3
- data/tracks/delphi/README.md +1 -1
- data/tracks/delphi/config.json +83 -1
- data/tracks/ecmascript/config.json +10 -0
- data/tracks/ecmascript/exercises/accumulate/accumulate.spec.js +3 -9
- data/tracks/ecmascript/exercises/acronym/acronym.spec.js +2 -2
- data/tracks/ecmascript/exercises/all-your-base/all-your-base.spec.js +131 -133
- data/tracks/ecmascript/exercises/all-your-base/example.js +1 -3
- data/tracks/ecmascript/exercises/allergies/allergies.spec.js +8 -10
- data/tracks/ecmascript/exercises/allergies/example.js +3 -5
- data/tracks/ecmascript/exercises/alphametics/alphametics.spec.js +61 -63
- data/tracks/ecmascript/exercises/alphametics/example.js +99 -99
- data/tracks/ecmascript/exercises/anagram/anagram.spec.js +35 -37
- data/tracks/ecmascript/exercises/anagram/example.js +1 -3
- data/tracks/ecmascript/exercises/atbash-cipher/atbash-cipher.spec.js +1 -3
- data/tracks/ecmascript/exercises/atbash-cipher/example.js +3 -3
- data/tracks/ecmascript/exercises/beer-song/beer-song.spec.js +0 -2
- data/tracks/ecmascript/exercises/beer-song/example.js +9 -9
- data/tracks/ecmascript/exercises/binary/binary.spec.js +1 -2
- data/tracks/ecmascript/exercises/binary/example.js +3 -3
- data/tracks/ecmascript/exercises/binary-search/binary-search.spec.js +1 -3
- data/tracks/ecmascript/exercises/binary-search-tree/binary-search-tree.spec.js +13 -15
- data/tracks/ecmascript/exercises/binary-search-tree/example.js +2 -2
- data/tracks/ecmascript/exercises/bob/bob.spec.js +1 -3
- data/tracks/ecmascript/exercises/bob/example.js +3 -3
- data/tracks/ecmascript/exercises/bracket-push/example.js +2 -2
- data/tracks/ecmascript/exercises/circular-buffer/circular-buffer.spec.js +10 -12
- data/tracks/ecmascript/exercises/circular-buffer/example.js +12 -11
- data/tracks/ecmascript/exercises/clock/clock.spec.js +0 -8
- data/tracks/ecmascript/exercises/clock/example.js +11 -11
- data/tracks/ecmascript/exercises/connect/connect.spec.js +75 -77
- data/tracks/ecmascript/exercises/connect/example.js +27 -29
- data/tracks/ecmascript/exercises/crypto-square/crypto-square.spec.js +11 -11
- data/tracks/ecmascript/exercises/crypto-square/example.js +11 -10
- data/tracks/ecmascript/exercises/custom-set/custom-set.spec.js +2 -4
- data/tracks/ecmascript/exercises/custom-set/example.js +1 -1
- data/tracks/ecmascript/exercises/diamond/diamond.spec.js +20 -21
- data/tracks/ecmascript/exercises/diamond/example.js +12 -13
- data/tracks/ecmascript/exercises/difference-of-squares/difference-of-squares.spec.js +0 -5
- data/tracks/ecmascript/exercises/diffie-hellman/diffie-hellman.spec.js +7 -28
- data/tracks/ecmascript/exercises/etl/etl.spec.js +36 -18
- data/tracks/ecmascript/exercises/etl/example.js +3 -3
- data/tracks/ecmascript/exercises/flatten-array/example.js +1 -1
- data/tracks/ecmascript/exercises/flatten-array/flatten-array.spec.js +2 -3
- data/tracks/ecmascript/exercises/food-chain/example.js +12 -12
- data/tracks/ecmascript/exercises/food-chain/food-chain.spec.js +0 -1
- data/tracks/ecmascript/exercises/gigasecond/example.js +1 -1
- data/tracks/ecmascript/exercises/gigasecond/gigasecond.spec.js +0 -1
- data/tracks/ecmascript/exercises/grade-school/grade-school.spec.js +18 -19
- data/tracks/ecmascript/exercises/grains/grains.spec.js +0 -1
- data/tracks/ecmascript/exercises/hamming/example.js +3 -3
- data/tracks/ecmascript/exercises/hamming/hamming.spec.js +5 -6
- data/tracks/ecmascript/exercises/hello-world/example.js +1 -1
- data/tracks/ecmascript/exercises/hello-world/hello-world.spec.js +1 -1
- data/tracks/ecmascript/exercises/hexadecimal/example.js +2 -2
- data/tracks/ecmascript/exercises/hexadecimal/hexadecimal.spec.js +9 -11
- data/tracks/ecmascript/exercises/isogram/isogram.spec.js +22 -23
- data/tracks/ecmascript/exercises/kindergarten-garden/example.js +7 -7
- data/tracks/ecmascript/exercises/kindergarten-garden/kindergarten-garden.spec.js +0 -5
- data/tracks/ecmascript/exercises/largest-series-product/example.js +4 -8
- data/tracks/ecmascript/exercises/largest-series-product/largest-series-product.spec.js +5 -7
- data/tracks/ecmascript/exercises/leap/leap.spec.js +4 -6
- data/tracks/ecmascript/exercises/linked-list/example.js +2 -2
- data/tracks/ecmascript/exercises/list-ops/example.js +19 -19
- data/tracks/ecmascript/exercises/list-ops/list-ops.spec.js +2 -18
- data/tracks/ecmascript/exercises/luhn/example.js +1 -1
- data/tracks/ecmascript/exercises/luhn/luhn.spec.js +1 -3
- data/tracks/ecmascript/exercises/matrix/example.js +2 -4
- data/tracks/ecmascript/exercises/matrix/matrix.spec.js +0 -2
- data/tracks/ecmascript/exercises/meetup/example.js +12 -15
- data/tracks/ecmascript/exercises/meetup/meetup.spec.js +0 -2
- data/tracks/ecmascript/exercises/minesweeper/example.js +60 -0
- data/tracks/ecmascript/exercises/minesweeper/minesweeper.spec.js +174 -0
- data/tracks/ecmascript/exercises/minesweeper/package.json +69 -0
- data/tracks/ecmascript/exercises/nth-prime/example.js +3 -2
- data/tracks/ecmascript/exercises/nth-prime/nth-prime.spec.js +0 -1
- data/tracks/ecmascript/exercises/ocr-numbers/example.js +3 -3
- data/tracks/ecmascript/exercises/ocr-numbers/ocr-numbers.spec.js +16 -18
- data/tracks/ecmascript/exercises/octal/example.js +1 -1
- data/tracks/ecmascript/exercises/octal/octal.spec.js +0 -2
- data/tracks/ecmascript/exercises/palindrome-products/example.js +14 -11
- data/tracks/ecmascript/exercises/palindrome-products/palindrome-products.spec.js +15 -18
- data/tracks/ecmascript/exercises/pangram/example.js +6 -5
- data/tracks/ecmascript/exercises/pangram/pangram.spec.js +10 -12
- data/tracks/ecmascript/exercises/pascals-triangle/example.js +2 -2
- data/tracks/ecmascript/exercises/pascals-triangle/pascals-triangle.spec.js +6 -8
- data/tracks/ecmascript/exercises/perfect-numbers/example.js +3 -5
- data/tracks/ecmascript/exercises/perfect-numbers/perfect-numbers.spec.js +0 -10
- data/tracks/ecmascript/exercises/phone-number/example.js +2 -2
- data/tracks/ecmascript/exercises/phone-number/phone-number.spec.js +0 -2
- data/tracks/ecmascript/exercises/pig-latin/example.js +4 -4
- data/tracks/ecmascript/exercises/pig-latin/pig-latin.spec.js +0 -1
- data/tracks/ecmascript/exercises/prime-factors/example.js +2 -2
- data/tracks/ecmascript/exercises/prime-factors/prime-factors.spec.js +0 -2
- data/tracks/ecmascript/exercises/pythagorean-triplet/pythagorean-triplet.spec.js +3 -11
- data/tracks/ecmascript/exercises/queen-attack/example.js +17 -17
- data/tracks/ecmascript/exercises/queen-attack/queen-attack.spec.js +7 -8
- data/tracks/ecmascript/exercises/raindrops/example.js +1 -1
- data/tracks/ecmascript/exercises/raindrops/raindrops.spec.js +1 -2
- data/tracks/ecmascript/exercises/rna-transcription/example.js +5 -5
- data/tracks/ecmascript/exercises/rna-transcription/rna-transcription.spec.js +4 -5
- data/tracks/ecmascript/exercises/robot-name/example.js +6 -6
- data/tracks/ecmascript/exercises/robot-name/robot-name.spec.js +10 -11
- data/tracks/ecmascript/exercises/robot-simulator/example.js +1 -1
- data/tracks/ecmascript/exercises/robot-simulator/robot-simulator.spec.js +31 -32
- data/tracks/ecmascript/exercises/roman-numerals/example.js +16 -16
- data/tracks/ecmascript/exercises/saddle-points/saddle-points.spec.js +3 -3
- data/tracks/ecmascript/exercises/say/example.js +25 -25
- data/tracks/ecmascript/exercises/say/say.spec.js +2 -3
- data/tracks/ecmascript/exercises/scrabble-score/example.js +27 -9
- data/tracks/ecmascript/exercises/scrabble-score/scrabble-score.spec.js +6 -7
- data/tracks/ecmascript/exercises/secret-handshake/example.js +2 -3
- data/tracks/ecmascript/exercises/secret-handshake/secret-handshake.spec.js +3 -5
- data/tracks/ecmascript/exercises/series/series.spec.js +1 -3
- data/tracks/ecmascript/exercises/sieve/example.js +4 -3
- data/tracks/ecmascript/exercises/sieve/sieve.spec.js +0 -2
- data/tracks/ecmascript/exercises/simple-cipher/example.js +8 -9
- data/tracks/ecmascript/exercises/simple-cipher/simple-cipher.spec.js +4 -4
- data/tracks/ecmascript/exercises/space-age/example.js +1 -1
- data/tracks/ecmascript/exercises/space-age/space-age.spec.js +9 -11
- data/tracks/ecmascript/exercises/strain/example.js +4 -4
- data/tracks/ecmascript/exercises/strain/strain.spec.js +14 -16
- data/tracks/ecmascript/exercises/sum-of-multiples/example.js +4 -4
- data/tracks/ecmascript/exercises/triangle/triangle.spec.js +2 -4
- data/tracks/ecmascript/exercises/trinary/example.js +3 -3
- data/tracks/ecmascript/exercises/trinary/trinary.spec.js +0 -2
- data/tracks/ecmascript/exercises/two-bucket/example.js +30 -27
- data/tracks/ecmascript/exercises/two-bucket/two-bucket.spec.js +4 -8
- data/tracks/ecmascript/exercises/word-count/example.js +2 -2
- data/tracks/ecmascript/exercises/word-count/word-count.spec.js +2 -3
- data/tracks/ecmascript/exercises/wordy/example.js +6 -6
- data/tracks/ecmascript/exercises/wordy/wordy.spec.js +2 -4
- data/tracks/factor/config.json +15 -6
- data/tracks/fortran/.travis.yml +1 -1
- data/tracks/fsharp/config.json +312 -10
- data/tracks/go/README.md +1 -1
- data/tracks/go/config.json +523 -155
- data/tracks/haskell/README.md +2 -2
- data/tracks/haskell/config.json +256 -7
- data/tracks/haxe/.travis.yml +1 -1
- data/tracks/haxe/Makefile +2 -2
- data/tracks/haxe/config.json +8 -5
- data/tracks/java/CONTRIBUTING.md +2 -2
- data/tracks/java/config.json +277 -17
- data/tracks/java/exercises/rotational-cipher/build.gradle +17 -0
- data/tracks/java/exercises/rotational-cipher/src/example/java/RotationalCipher.java +37 -0
- data/tracks/java/exercises/rotational-cipher/src/main/java/.keep +0 -0
- data/tracks/java/exercises/rotational-cipher/src/test/java/RotationalCipherTest.java +81 -0
- data/tracks/java/exercises/settings.gradle +1 -0
- data/tracks/java/exercises/twelve-days/src/main/java/TwelveDays.java +4 -0
- data/tracks/julia/.travis.yml +1 -1
- data/tracks/julia/README.md +1 -1
- data/tracks/kotlin/README.md +2 -2
- data/tracks/kotlin/exercises/hello-world/TUTORIAL.md +3 -3
- data/tracks/lisp/config.json +97 -3
- data/tracks/lisp/exercises/pascals-triangle/example.lisp +21 -0
- data/tracks/lisp/exercises/pascals-triangle/pascal.lisp +7 -0
- data/tracks/lisp/exercises/pascals-triangle/pascals-triangle-test.lisp +34 -0
- data/tracks/lua/.travis.yml +1 -1
- data/tracks/lua/README.md +1 -1
- data/tracks/mips/.travis.yml +1 -1
- data/tracks/mips/config.json +56 -17
- data/tracks/nasm/.travis.yml +1 -1
- data/tracks/nim/.travis.yml +1 -1
- data/tracks/ocaml/README.md +3 -3
- data/tracks/ocaml/config.json +130 -4
- data/tracks/perl5/docs/TESTS.md +40 -26
- data/tracks/plsql/.travis.yml +1 -1
- data/tracks/plsql/config.json +40 -13
- data/tracks/pony/.travis.yml +1 -1
- data/tracks/pony/bin/install-deps +4 -3
- data/tracks/prolog/.travis.yml +1 -1
- data/tracks/r/README.md +5 -5
- data/tracks/r/config.json +102 -30
- data/tracks/rust/.travis.yml +1 -1
- data/tracks/rust/config.json +172 -4
- data/tracks/rust/docs/EXERCISE_README_INSERT.md +1 -1
- data/tracks/sml/config.json +26 -3
- data/tracks/vimscript/config.json +60 -3
- metadata +16 -1
|
@@ -2,17 +2,16 @@ import circularBuffer from './circular-buffer';
|
|
|
2
2
|
import { BufferFullError, BufferEmptyError } from './circular-buffer';
|
|
3
3
|
|
|
4
4
|
describe('CircularBuffer', () => {
|
|
5
|
-
|
|
6
5
|
test('reading an empty buffer throws a BufferEmptyError', () => {
|
|
7
6
|
const buffer = circularBuffer(1);
|
|
8
|
-
expect(()=>buffer.read()).toThrow(BufferEmptyError);
|
|
7
|
+
expect(() => buffer.read()).toThrow(BufferEmptyError);
|
|
9
8
|
});
|
|
10
9
|
|
|
11
10
|
xtest('write and read back one item', () => {
|
|
12
11
|
const buffer = circularBuffer(1);
|
|
13
12
|
buffer.write('1');
|
|
14
13
|
expect(buffer.read()).toBe('1');
|
|
15
|
-
expect(()=>buffer.read()).toThrow(BufferEmptyError);
|
|
14
|
+
expect(() => buffer.read()).toThrow(BufferEmptyError);
|
|
16
15
|
});
|
|
17
16
|
|
|
18
17
|
xtest('write and read back multiple items', () => {
|
|
@@ -21,7 +20,7 @@ describe('CircularBuffer', () => {
|
|
|
21
20
|
buffer.write('2');
|
|
22
21
|
expect(buffer.read()).toBe('1');
|
|
23
22
|
expect(buffer.read()).toBe('2');
|
|
24
|
-
expect(()=>buffer.read()).toThrow(BufferEmptyError);
|
|
23
|
+
expect(() => buffer.read()).toThrow(BufferEmptyError);
|
|
25
24
|
});
|
|
26
25
|
|
|
27
26
|
xtest('clearing a buffer', () => {
|
|
@@ -29,7 +28,7 @@ describe('CircularBuffer', () => {
|
|
|
29
28
|
buffer.write('1');
|
|
30
29
|
buffer.write('2');
|
|
31
30
|
buffer.clear();
|
|
32
|
-
expect(()=>buffer.read()).toThrow(BufferEmptyError);
|
|
31
|
+
expect(() => buffer.read()).toThrow(BufferEmptyError);
|
|
33
32
|
buffer.write('3');
|
|
34
33
|
buffer.write('4');
|
|
35
34
|
expect(buffer.read()).toBe('3');
|
|
@@ -58,7 +57,7 @@ describe('CircularBuffer', () => {
|
|
|
58
57
|
const buffer = circularBuffer(3);
|
|
59
58
|
buffer.write(null);
|
|
60
59
|
buffer.write(undefined);
|
|
61
|
-
[1,2,3].map(i => buffer.write(i.toString()));
|
|
60
|
+
[1, 2, 3].map(i => buffer.write(i.toString()));
|
|
62
61
|
expect(buffer.read()).toBe('1');
|
|
63
62
|
});
|
|
64
63
|
|
|
@@ -76,7 +75,7 @@ describe('CircularBuffer', () => {
|
|
|
76
75
|
buffer.forceWrite('A');
|
|
77
76
|
expect(buffer.read()).toBe('2');
|
|
78
77
|
expect(buffer.read()).toBe('A');
|
|
79
|
-
expect(()=>buffer.read()).toThrow(BufferEmptyError);
|
|
78
|
+
expect(() => buffer.read()).toThrow(BufferEmptyError);
|
|
80
79
|
});
|
|
81
80
|
|
|
82
81
|
xtest('forced writes act like write in a non-full buffer', () => {
|
|
@@ -85,17 +84,17 @@ describe('CircularBuffer', () => {
|
|
|
85
84
|
buffer.forceWrite('2');
|
|
86
85
|
expect(buffer.read()).toBe('1');
|
|
87
86
|
expect(buffer.read()).toBe('2');
|
|
88
|
-
expect(()=>buffer.read()).toThrow(BufferEmptyError);
|
|
87
|
+
expect(() => buffer.read()).toThrow(BufferEmptyError);
|
|
89
88
|
});
|
|
90
89
|
|
|
91
90
|
xtest('alternate force write and read into full buffer', () => {
|
|
92
91
|
const buffer = circularBuffer(5);
|
|
93
|
-
[1,2,3].map(i => buffer.write(i.toString()));
|
|
92
|
+
[1, 2, 3].map(i => buffer.write(i.toString()));
|
|
94
93
|
buffer.read();
|
|
95
94
|
buffer.read();
|
|
96
95
|
buffer.write('4');
|
|
97
96
|
buffer.read();
|
|
98
|
-
[5,6,7,8].map(i => buffer.write(i.toString()));
|
|
97
|
+
[5, 6, 7, 8].map(i => buffer.write(i.toString()));
|
|
99
98
|
buffer.forceWrite('A');
|
|
100
99
|
buffer.forceWrite('B');
|
|
101
100
|
expect(buffer.read()).toBe('6');
|
|
@@ -103,7 +102,6 @@ describe('CircularBuffer', () => {
|
|
|
103
102
|
expect(buffer.read()).toBe('8');
|
|
104
103
|
expect(buffer.read()).toBe('A');
|
|
105
104
|
expect(buffer.read()).toBe('B');
|
|
106
|
-
expect(()=>buffer.read()).toThrow(BufferEmptyError);
|
|
105
|
+
expect(() => buffer.read()).toThrow(BufferEmptyError);
|
|
107
106
|
});
|
|
108
|
-
|
|
109
107
|
});
|
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
let buffer,
|
|
1
|
+
let buffer,
|
|
2
|
+
bufferMax;
|
|
2
3
|
|
|
3
4
|
export class BufferEmptyError extends Error {
|
|
4
5
|
constructor(message) {
|
|
5
6
|
super();
|
|
6
7
|
this.message = message || 'Buffer is empty.';
|
|
7
8
|
}
|
|
8
|
-
}
|
|
9
|
+
}
|
|
9
10
|
export class BufferFullError extends Error {
|
|
10
11
|
constructor(message) {
|
|
11
12
|
super();
|
|
12
13
|
this.message = message || 'Buffer is full.';
|
|
13
14
|
}
|
|
14
|
-
}
|
|
15
|
+
}
|
|
15
16
|
|
|
16
17
|
const read = () => {
|
|
17
|
-
if (buffer.length === 0){
|
|
18
|
+
if (buffer.length === 0) {
|
|
18
19
|
throw new BufferEmptyError();
|
|
19
20
|
}
|
|
20
|
-
return buffer.splice(0,1)[0];
|
|
21
|
+
return buffer.splice(0, 1)[0];
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const write = (value) => {
|
|
24
|
-
if (buffer.length === bufferMax){
|
|
25
|
+
if (buffer.length === bufferMax) {
|
|
25
26
|
throw new BufferFullError();
|
|
26
27
|
}
|
|
27
28
|
value ? buffer.push(value) : null;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
const forceWrite = (value) => {
|
|
31
|
-
if (buffer.length === bufferMax){
|
|
32
|
+
if (buffer.length === bufferMax) {
|
|
32
33
|
read();
|
|
33
34
|
}
|
|
34
35
|
write(value);
|
|
@@ -40,10 +41,10 @@ const CircularBuffer = (capacity) => {
|
|
|
40
41
|
buffer = [];
|
|
41
42
|
bufferMax = capacity;
|
|
42
43
|
return {
|
|
43
|
-
read
|
|
44
|
-
write
|
|
45
|
-
forceWrite
|
|
46
|
-
clear
|
|
44
|
+
read,
|
|
45
|
+
write,
|
|
46
|
+
forceWrite,
|
|
47
|
+
clear,
|
|
47
48
|
};
|
|
48
49
|
};
|
|
49
50
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import at from './clock';
|
|
2
2
|
|
|
3
3
|
describe('Clock', () => {
|
|
4
|
-
|
|
5
4
|
describe('Creating a new clock with an initial time', () => {
|
|
6
|
-
|
|
7
5
|
test('on the hour', () => {
|
|
8
6
|
expect(at(8).toString()).toEqual('08:00');
|
|
9
7
|
});
|
|
@@ -81,7 +79,6 @@ describe('Clock', () => {
|
|
|
81
79
|
});
|
|
82
80
|
|
|
83
81
|
describe('Adding and subtracting minutes', () => {
|
|
84
|
-
|
|
85
82
|
xtest('add minutes', () => {
|
|
86
83
|
expect(at(10, 0).plus(3).toString()).toEqual('10:03');
|
|
87
84
|
});
|
|
@@ -145,11 +142,9 @@ describe('Clock', () => {
|
|
|
145
142
|
xtest('subtract more than two days', () => {
|
|
146
143
|
expect(at(2, 20).minus(3000).toString()).toEqual('00:20');
|
|
147
144
|
});
|
|
148
|
-
|
|
149
145
|
});
|
|
150
146
|
|
|
151
147
|
describe('Construct two separate clocks, set times, test if they are equal', () => {
|
|
152
|
-
|
|
153
148
|
xtest('clocks with same time', () => {
|
|
154
149
|
expect(at(15, 37).equals(at(15, 37))).toBeTruthy();
|
|
155
150
|
});
|
|
@@ -209,9 +204,6 @@ describe('Clock', () => {
|
|
|
209
204
|
xtest('clocks with negative hours and minutes that wrap', () => {
|
|
210
205
|
expect(at(18, 7).equals(at(-54, -11513))).toBeTruthy();
|
|
211
206
|
});
|
|
212
|
-
|
|
213
207
|
});
|
|
214
|
-
|
|
215
208
|
});
|
|
216
|
-
|
|
217
209
|
});
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export default function(hour, minute) {
|
|
1
|
+
export default function (hour, minute) {
|
|
2
2
|
const MINUTESPERDAY = 1440;
|
|
3
3
|
const HOURSPERDAY = 24;
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
hour
|
|
7
|
-
minute: minute || 0
|
|
5
|
+
const clock = {
|
|
6
|
+
hour,
|
|
7
|
+
minute: minute || 0,
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
function formatNum(num) {
|
|
11
11
|
const numString = num.toString();
|
|
12
|
-
return numString.length === 1 ?
|
|
12
|
+
return numString.length === 1 ? `0${numString}` : numString;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
function adjustTime(delta) {
|
|
@@ -27,10 +27,10 @@ export default function(hour, minute) {
|
|
|
27
27
|
adjustTime(0);
|
|
28
28
|
|
|
29
29
|
return {
|
|
30
|
-
clock
|
|
31
|
-
toString: () => formatNum(clock.hour)
|
|
32
|
-
plus
|
|
33
|
-
minus
|
|
34
|
-
equals:
|
|
35
|
-
}
|
|
30
|
+
clock,
|
|
31
|
+
toString: () => `${formatNum(clock.hour)}:${formatNum(clock.minute)}`,
|
|
32
|
+
plus(minutes) { adjustTime(minutes); return this; },
|
|
33
|
+
minus(minutes) { adjustTime(-minutes); return this; },
|
|
34
|
+
equals: otherClock => clock.hour === otherClock.clock.hour && clock.minute === otherClock.clock.minute,
|
|
35
|
+
};
|
|
36
36
|
}
|
|
@@ -1,110 +1,108 @@
|
|
|
1
1
|
import Board from './connect';
|
|
2
2
|
|
|
3
3
|
describe('Judging a game of connect', () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
" . . . . ."
|
|
4
|
+
test('an empty board has no winner', () => {
|
|
5
|
+
const board = [
|
|
6
|
+
'. . . . .',
|
|
7
|
+
' . . . . .',
|
|
8
|
+
' . . . . .',
|
|
9
|
+
' . . . . .',
|
|
10
|
+
' . . . . .',
|
|
12
11
|
];
|
|
13
|
-
expect(new Board(board).winner()).toEqual(
|
|
12
|
+
expect(new Board(board).winner()).toEqual('');
|
|
14
13
|
});
|
|
15
14
|
|
|
16
|
-
xtest(
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
xtest('X can win on a 1x1 board', () => {
|
|
16
|
+
const board = [
|
|
17
|
+
'X',
|
|
19
18
|
];
|
|
20
|
-
expect(new Board(board).winner()).toEqual(
|
|
19
|
+
expect(new Board(board).winner()).toEqual('X');
|
|
21
20
|
});
|
|
22
21
|
|
|
23
|
-
xtest(
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
xtest('O can win on a 1x1 board', () => {
|
|
23
|
+
const board = [
|
|
24
|
+
'O',
|
|
26
25
|
];
|
|
27
|
-
expect(new Board(board).winner()).toEqual(
|
|
26
|
+
expect(new Board(board).winner()).toEqual('O');
|
|
28
27
|
});
|
|
29
28
|
|
|
30
|
-
xtest(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
xtest('only edges does not make a winner', () => {
|
|
30
|
+
const board = [
|
|
31
|
+
'O O O X',
|
|
32
|
+
' X . . X',
|
|
33
|
+
' X . . X',
|
|
34
|
+
' X O O O',
|
|
36
35
|
];
|
|
37
|
-
expect(new Board(board).winner()).toEqual(
|
|
36
|
+
expect(new Board(board).winner()).toEqual('');
|
|
38
37
|
});
|
|
39
38
|
|
|
40
|
-
xtest(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
xtest('illegal diagonal does not make a winner', () => {
|
|
40
|
+
const board = [
|
|
41
|
+
'X O . .',
|
|
42
|
+
' O X X X',
|
|
43
|
+
' O X O .',
|
|
44
|
+
' . O X .',
|
|
45
|
+
' X X O O',
|
|
47
46
|
];
|
|
48
|
-
expect(new Board(board).winner()).toEqual(
|
|
47
|
+
expect(new Board(board).winner()).toEqual('');
|
|
49
48
|
});
|
|
50
49
|
|
|
51
|
-
xtest(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
xtest('nobody wins crossing adjacent angles', () => {
|
|
51
|
+
const board = [
|
|
52
|
+
'X . . .',
|
|
53
|
+
' . X O .',
|
|
54
|
+
' O . X O',
|
|
55
|
+
' . O . X',
|
|
56
|
+
' . . O .',
|
|
58
57
|
];
|
|
59
|
-
expect(new Board(board).winner()).toEqual(
|
|
58
|
+
expect(new Board(board).winner()).toEqual('');
|
|
60
59
|
});
|
|
61
60
|
|
|
62
|
-
xtest(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
xtest('X wins crossing from left to right', () => {
|
|
62
|
+
const board = [
|
|
63
|
+
'. O . .',
|
|
64
|
+
' O X X X',
|
|
65
|
+
' O X O .',
|
|
66
|
+
' X X O X',
|
|
67
|
+
' . O X .',
|
|
69
68
|
];
|
|
70
|
-
expect(new Board(board).winner()).toEqual(
|
|
69
|
+
expect(new Board(board).winner()).toEqual('X');
|
|
71
70
|
});
|
|
72
71
|
|
|
73
|
-
xtest(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
xtest('O wins crossing from top to bottom', () => {
|
|
73
|
+
const board = [
|
|
74
|
+
'. O . .',
|
|
75
|
+
' O X X X',
|
|
76
|
+
' O O O .',
|
|
77
|
+
' X X O X',
|
|
78
|
+
' . O X .',
|
|
80
79
|
];
|
|
81
|
-
expect(new Board(board).winner()).toEqual(
|
|
80
|
+
expect(new Board(board).winner()).toEqual('O');
|
|
82
81
|
});
|
|
83
82
|
|
|
84
|
-
xtest(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
xtest('X wins using a convoluted path', () => {
|
|
84
|
+
const board = [
|
|
85
|
+
'. X X . .',
|
|
86
|
+
' X . X . X',
|
|
87
|
+
' . X . X .',
|
|
88
|
+
' . X X . .',
|
|
89
|
+
' O O O O O',
|
|
91
90
|
];
|
|
92
|
-
expect(new Board(board).winner()).toEqual(
|
|
91
|
+
expect(new Board(board).winner()).toEqual('X');
|
|
93
92
|
});
|
|
94
93
|
|
|
95
|
-
xtest(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
94
|
+
xtest('X wins using a spiral path', () => {
|
|
95
|
+
const board = [
|
|
96
|
+
'O X X X X X X X X',
|
|
97
|
+
' O X O O O O O O O',
|
|
98
|
+
' O X O X X X X X O',
|
|
99
|
+
' O X O X O O O X O',
|
|
100
|
+
' O X O X X X O X O',
|
|
101
|
+
' O X O O O X O X O',
|
|
102
|
+
' O X X X X X O X O',
|
|
103
|
+
' O O O O O O O X O',
|
|
104
|
+
' X X X X X X X X O',
|
|
106
105
|
];
|
|
107
|
-
expect(new Board(board).winner()).toEqual(
|
|
106
|
+
expect(new Board(board).winner()).toEqual('X');
|
|
108
107
|
});
|
|
109
|
-
|
|
110
108
|
});
|
|
@@ -4,67 +4,65 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export default class {
|
|
6
6
|
constructor(board) {
|
|
7
|
-
this.board = board.map(
|
|
7
|
+
this.board = board.map(b => [...b]);
|
|
8
8
|
}
|
|
9
9
|
winner() {
|
|
10
|
-
const players = ['X','O'];
|
|
11
|
-
for(
|
|
12
|
-
if(this.checkWin(player)) {
|
|
10
|
+
const players = ['X', 'O'];
|
|
11
|
+
for (const player of players) {
|
|
12
|
+
if (this.checkWin(player)) {
|
|
13
13
|
return player;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return '';
|
|
17
17
|
}
|
|
18
18
|
checkWin(player) {
|
|
19
|
-
|
|
20
|
-
for(
|
|
21
|
-
if(this.search(position, player,[])) {
|
|
19
|
+
const positions = this.startPositions(player);
|
|
20
|
+
for (const position of positions) {
|
|
21
|
+
if (this.search(position, player, [])) {
|
|
22
22
|
return true;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
27
|
search(pos, XorO, checked) {
|
|
28
|
-
if(!
|
|
28
|
+
if (!this.matches(pos, XorO)) {
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
|
-
if(this.winningSpot(pos, XorO)) {
|
|
31
|
+
if (this.winningSpot(pos, XorO)) {
|
|
32
32
|
return true;
|
|
33
33
|
}
|
|
34
34
|
checked = checked.slice(0);
|
|
35
35
|
checked.push(pos);
|
|
36
|
-
const matches = this.neighbors(pos).filter(({x,y}) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if(matches.length === 0) {
|
|
40
|
-
return false;
|
|
36
|
+
const matches = this.neighbors(pos).filter(({ x, y }) => this.matches({ x, y }, XorO) && checked.filter(spot => spot.x === x && spot.y === y).length === 0);
|
|
37
|
+
if (matches.length === 0) {
|
|
38
|
+
return false;
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
return matches.filter(spot => this.search(spot, XorO, checked)).length > 0;
|
|
44
42
|
}
|
|
45
|
-
neighbors({x,y}) {
|
|
43
|
+
neighbors({ x, y }) {
|
|
46
44
|
return [
|
|
47
|
-
{x, y: y + 2},
|
|
48
|
-
{x, y: y - 2},
|
|
45
|
+
{ x, y: y + 2 },
|
|
46
|
+
{ x, y: y - 2 },
|
|
49
47
|
|
|
50
|
-
{x: x + 1, y: y + 1},
|
|
51
|
-
{x: x - 1, y: y + 1},
|
|
48
|
+
{ x: x + 1, y: y + 1 },
|
|
49
|
+
{ x: x - 1, y: y + 1 },
|
|
52
50
|
|
|
53
|
-
{x: x + 1, y: y - 1},
|
|
54
|
-
{x: x - 1, y: y - 1}
|
|
51
|
+
{ x: x + 1, y: y - 1 },
|
|
52
|
+
{ x: x - 1, y: y - 1 },
|
|
55
53
|
];
|
|
56
54
|
}
|
|
57
55
|
startPositions(XorO) {
|
|
58
|
-
return XorO ===
|
|
59
|
-
this.board.map((pos, i) => ({x:i,y:i})) :
|
|
60
|
-
this.board[0].map((pos, i) => ({x:0, y:i}));
|
|
56
|
+
return XorO === 'X' ?
|
|
57
|
+
this.board.map((pos, i) => ({ x: i, y: i })) :
|
|
58
|
+
this.board[0].map((pos, i) => ({ x: 0, y: i }));
|
|
61
59
|
}
|
|
62
|
-
winningSpot({x,y},XorO) {
|
|
63
|
-
return XorO ===
|
|
64
|
-
y === this.board[0].length - 1 + x:
|
|
60
|
+
winningSpot({ x, y }, XorO) {
|
|
61
|
+
return XorO === 'X' ?
|
|
62
|
+
y === this.board[0].length - 1 + x :
|
|
65
63
|
x === this.board.length - 1;
|
|
66
64
|
}
|
|
67
|
-
matches({x,y}, XorO) {
|
|
65
|
+
matches({ x, y }, XorO) {
|
|
68
66
|
return this.board[x] !== undefined && this.board[x][y] === XorO;
|
|
69
67
|
}
|
|
70
68
|
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
import Crypto from './crypto-square';
|
|
2
2
|
|
|
3
|
-
describe('Crypto',() => {
|
|
4
|
-
test('normalize strange characters',() => {
|
|
3
|
+
describe('Crypto', () => {
|
|
4
|
+
test('normalize strange characters', () => {
|
|
5
5
|
const crypto = new Crypto('s#$%^&plunk');
|
|
6
6
|
expect(crypto.normalizePlaintext()).toEqual('splunk');
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
xtest('normalize numbers',() => {
|
|
9
|
+
xtest('normalize numbers', () => {
|
|
10
10
|
const crypto = new Crypto('1, 2, 3 GO!');
|
|
11
11
|
expect(crypto.normalizePlaintext()).toEqual('123go');
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
xtest('size of small square',() => {
|
|
14
|
+
xtest('size of small square', () => {
|
|
15
15
|
const crypto = new Crypto('1234');
|
|
16
16
|
expect(crypto.size()).toEqual(2);
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
xtest('size of small square with additional non-number chars',() => {
|
|
19
|
+
xtest('size of small square with additional non-number chars', () => {
|
|
20
20
|
const crypto = new Crypto('1 2 3 4');
|
|
21
21
|
expect(crypto.size()).toEqual(2);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
xtest('size of slightly larger square',() => {
|
|
24
|
+
xtest('size of slightly larger square', () => {
|
|
25
25
|
const crypto = new Crypto('123456789');
|
|
26
26
|
expect(crypto.size()).toEqual(3);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
xtest('size of non-perfect square',() => {
|
|
29
|
+
xtest('size of non-perfect square', () => {
|
|
30
30
|
const crypto = new Crypto('123456789abc');
|
|
31
31
|
expect(crypto.size()).toEqual(4);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
xtest('plain text segments',() => {
|
|
34
|
+
xtest('plain text segments', () => {
|
|
35
35
|
const crypto = new Crypto('Never vex thine heart with idle woes');
|
|
36
36
|
expect(crypto.plaintextSegments()).toEqual(['neverv', 'exthin', 'eheart', 'withid', 'lewoes']);
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
xtest('plain text segments',() => {
|
|
39
|
+
xtest('plain text segments', () => {
|
|
40
40
|
const crypto = new Crypto('ZOMG! ZOMBIES!!!');
|
|
41
41
|
expect(crypto.plaintextSegments()).toEqual(['zomg', 'zomb', 'ies']);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
xtest('cipher text',() => {
|
|
44
|
+
xtest('cipher text', () => {
|
|
45
45
|
const crypto = new Crypto('Time is an illusion. Lunchtime doubly so.');
|
|
46
46
|
expect(crypto.ciphertext()).toEqual('tasneyinicdsmiohooelntuillibsuuml');
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
xtest('cipher text',() => {
|
|
49
|
+
xtest('cipher text', () => {
|
|
50
50
|
const crypto = new Crypto('We all know interspecies romance is weird.');
|
|
51
51
|
expect(crypto.ciphertext()).toEqual('wneiaweoreneawssciliprerlneoidktcms');
|
|
52
52
|
});
|
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
export default class Square {
|
|
2
|
-
constructor
|
|
2
|
+
constructor(input) {
|
|
3
3
|
this.input = input;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
normalizePlaintext
|
|
7
|
-
return this.input.toLowerCase().replace(/[^a-zA-Z0-9]/g,'');
|
|
6
|
+
normalizePlaintext() {
|
|
7
|
+
return this.input.toLowerCase().replace(/[^a-zA-Z0-9]/g, '');
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
size
|
|
10
|
+
size() {
|
|
11
11
|
const realLength = Math.sqrt(this.normalizePlaintext().length);
|
|
12
12
|
return Math.ceil(realLength);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
plaintextSegments
|
|
15
|
+
plaintextSegments() {
|
|
16
16
|
const plainText = this.normalizePlaintext();
|
|
17
17
|
const chunkSize = this.size();
|
|
18
18
|
|
|
19
|
-
const splitRegex = new RegExp(
|
|
19
|
+
const splitRegex = new RegExp(`.{1,${chunkSize}}`, 'g');
|
|
20
20
|
return plainText.match(splitRegex);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
ciphertext
|
|
23
|
+
ciphertext() {
|
|
24
24
|
const textSegments = this.plaintextSegments(),
|
|
25
25
|
columns = [];
|
|
26
|
-
let i,
|
|
26
|
+
let i,
|
|
27
|
+
j,
|
|
27
28
|
currentSegment,
|
|
28
29
|
currentLetter;
|
|
29
30
|
|
|
@@ -47,9 +48,9 @@ export default class Square {
|
|
|
47
48
|
return columns.join('');
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
normalizeCiphertext
|
|
51
|
+
normalizeCiphertext() {
|
|
51
52
|
const chunkSize = this.size();
|
|
52
|
-
const splitRegex = new RegExp(
|
|
53
|
+
const splitRegex = new RegExp(`.{1,${chunkSize}}`, 'g');
|
|
53
54
|
return this.ciphertext().match(splitRegex).join(' ');
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import CustomSet from './custom-set';
|
|
2
2
|
|
|
3
3
|
describe('CustomSet', () => {
|
|
4
|
-
|
|
5
|
-
test('can delete elements', () =>{
|
|
4
|
+
test('can delete elements', () => {
|
|
6
5
|
const expected = new CustomSet([1, 3]);
|
|
7
6
|
const actual = new CustomSet([3, 2, 1]).delete(2);
|
|
8
7
|
expect(actual.eql(expected)).toBe(true);
|
|
@@ -12,7 +11,7 @@ describe('CustomSet', () => {
|
|
|
12
11
|
expect(actual2.eql(expected2)).toBe(true);
|
|
13
12
|
});
|
|
14
13
|
|
|
15
|
-
xtest('can check for difference', () =>{
|
|
14
|
+
xtest('can check for difference', () => {
|
|
16
15
|
const expected = new CustomSet([1, 3]);
|
|
17
16
|
const actual = new CustomSet([3, 2, 1]).difference(new CustomSet([2, 4]));
|
|
18
17
|
expect(actual.eql(expected)).toBe(true);
|
|
@@ -113,5 +112,4 @@ describe('CustomSet', () => {
|
|
|
113
112
|
const expected4 = new CustomSet();
|
|
114
113
|
expect(actual4.eql(expected4)).toBe(true);
|
|
115
114
|
});
|
|
116
|
-
|
|
117
115
|
});
|