trackler 2.2.1.57 → 2.2.1.58
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/custom-set/canonical-data.json +8 -1
- data/tracks/c/README.md +2 -44
- data/tracks/c/docs/CONTRIBUTING.md +93 -0
- data/tracks/c/docs/C_STYLE_GUIDE.md +1 -1
- data/tracks/clojure/config.json +27 -0
- data/tracks/clojure/exercises/accumulate/project.clj +1 -1
- data/tracks/clojure/exercises/acronym/project.clj +1 -1
- data/tracks/clojure/exercises/all-your-base/project.clj +1 -1
- data/tracks/clojure/exercises/allergies/project.clj +1 -1
- data/tracks/clojure/exercises/anagram/project.clj +1 -1
- data/tracks/clojure/exercises/atbash-cipher/project.clj +1 -1
- data/tracks/clojure/exercises/bank-account/project.clj +1 -1
- data/tracks/clojure/exercises/beer-song/project.clj +1 -1
- data/tracks/clojure/exercises/binary/project.clj +1 -1
- data/tracks/clojure/exercises/binary-search/project.clj +1 -1
- data/tracks/clojure/exercises/binary-search-tree/project.clj +1 -1
- data/tracks/clojure/exercises/bob/project.clj +1 -1
- data/tracks/clojure/exercises/bracket-push/project.clj +1 -1
- data/tracks/clojure/exercises/change/project.clj +1 -1
- data/tracks/clojure/exercises/clock/project.clj +1 -1
- data/tracks/clojure/exercises/collatz-conjecture/project.clj +1 -1
- data/tracks/clojure/exercises/complex-numbers/project.clj +1 -1
- data/tracks/clojure/exercises/crypto-square/project.clj +1 -1
- data/tracks/clojure/exercises/diamond/README.md +51 -0
- data/tracks/clojure/exercises/diamond/project.clj +4 -0
- data/tracks/clojure/exercises/diamond/src/example.clj +22 -0
- data/tracks/clojure/exercises/diamond/test/diamond_test.clj +79 -0
- data/tracks/clojure/exercises/difference-of-squares/project.clj +1 -1
- data/tracks/clojure/exercises/etl/project.clj +1 -1
- data/tracks/clojure/exercises/flatten-array/project.clj +1 -1
- data/tracks/clojure/exercises/gigasecond/project.clj +1 -1
- data/tracks/clojure/exercises/grade-school/project.clj +1 -1
- data/tracks/clojure/exercises/grains/project.clj +1 -1
- data/tracks/clojure/exercises/hamming/project.clj +1 -1
- data/tracks/clojure/exercises/hello-world/project.clj +1 -1
- data/tracks/clojure/exercises/hexadecimal/project.clj +1 -1
- data/tracks/clojure/exercises/isogram/project.clj +1 -1
- data/tracks/clojure/exercises/kindergarten-garden/project.clj +1 -1
- data/tracks/clojure/exercises/largest-series-product/project.clj +1 -1
- data/tracks/clojure/exercises/leap/project.clj +1 -1
- data/tracks/clojure/exercises/luhn/project.clj +1 -1
- data/tracks/clojure/exercises/meetup/project.clj +1 -1
- data/tracks/clojure/exercises/minesweeper/project.clj +1 -1
- data/tracks/clojure/exercises/nth-prime/project.clj +1 -1
- data/tracks/clojure/exercises/nucleotide-count/project.clj +1 -1
- data/tracks/clojure/exercises/octal/project.clj +1 -1
- data/tracks/clojure/exercises/pascals-triangle/project.clj +1 -1
- data/tracks/clojure/exercises/perfect-numbers/project.clj +1 -1
- data/tracks/clojure/exercises/phone-number/project.clj +1 -1
- data/tracks/clojure/exercises/pig-latin/project.clj +1 -1
- data/tracks/clojure/exercises/prime-factors/project.clj +1 -1
- data/tracks/clojure/exercises/protein-translation/README.md +40 -0
- data/tracks/clojure/exercises/protein-translation/project.clj +4 -0
- data/tracks/clojure/exercises/protein-translation/src/example.clj +19 -0
- data/tracks/clojure/exercises/protein-translation/test/protein_translation_test.clj +36 -0
- data/tracks/clojure/exercises/queen-attack/project.clj +1 -1
- data/tracks/clojure/exercises/raindrops/project.clj +1 -1
- data/tracks/clojure/exercises/rna-transcription/project.clj +1 -1
- data/tracks/clojure/exercises/robot-name/project.clj +1 -1
- data/tracks/clojure/exercises/robot-simulator/project.clj +1 -1
- data/tracks/clojure/exercises/roman-numerals/project.clj +1 -1
- data/tracks/clojure/exercises/rotational-cipher/project.clj +1 -1
- data/tracks/clojure/exercises/run-length-encoding/README.md +36 -0
- data/tracks/clojure/exercises/run-length-encoding/project.clj +4 -0
- data/tracks/clojure/exercises/run-length-encoding/src/example.clj +20 -0
- data/tracks/clojure/exercises/run-length-encoding/src/run_length_encoding.clj +11 -0
- data/tracks/clojure/exercises/run-length-encoding/test/run_length_encoding_test.clj +57 -0
- data/tracks/clojure/exercises/scrabble-score/project.clj +1 -1
- data/tracks/clojure/exercises/secret-handshake/project.clj +1 -1
- data/tracks/clojure/exercises/series/project.clj +1 -1
- data/tracks/clojure/exercises/sieve/project.clj +1 -1
- data/tracks/clojure/exercises/space-age/project.clj +1 -1
- data/tracks/clojure/exercises/spiral-matrix/project.clj +1 -1
- data/tracks/clojure/exercises/strain/project.clj +1 -1
- data/tracks/clojure/exercises/sublist/project.clj +1 -1
- data/tracks/clojure/exercises/sum-of-multiples/project.clj +1 -1
- data/tracks/clojure/exercises/triangle/project.clj +1 -1
- data/tracks/clojure/exercises/trinary/project.clj +1 -1
- data/tracks/clojure/exercises/word-count/project.clj +1 -1
- data/tracks/clojure/exercises/wordy/project.clj +1 -1
- data/tracks/clojure/project.clj +2 -2
- data/tracks/ecmascript/config.json +10 -15
- data/tracks/ecmascript/docs/TESTS.md +15 -0
- data/tracks/ecmascript/exercises/complex-numbers/README.md +68 -0
- data/tracks/ecmascript/exercises/complex-numbers/complex-numbers.spec.js +216 -0
- data/tracks/ecmascript/exercises/complex-numbers/example.js +43 -0
- data/tracks/ecmascript/exercises/{transpose → complex-numbers}/package.json +2 -2
- data/tracks/elixir/config.json +22 -1
- data/tracks/elixir/exercises/isbn-verifier/README.md +80 -0
- data/tracks/elixir/exercises/isbn-verifier/example.exs +36 -0
- data/tracks/elixir/exercises/isbn-verifier/isbn_verifier.exs +18 -0
- data/tracks/elixir/exercises/isbn-verifier/isbn_verifier_test.exs +75 -0
- data/tracks/elixir/exercises/spiral-matrix/README.md +65 -0
- data/tracks/elixir/exercises/spiral-matrix/example.exs +27 -0
- data/tracks/elixir/exercises/spiral-matrix/spiral.exs +9 -0
- data/tracks/elixir/exercises/spiral-matrix/spiral_test.exs +58 -0
- data/tracks/erlang/config.json +10 -0
- data/tracks/erlang/exercises/complex-numbers/HINTS.md +2 -0
- data/tracks/erlang/exercises/complex-numbers/README.md +85 -0
- data/tracks/erlang/exercises/complex-numbers/include/exercism.hrl +11 -0
- data/tracks/erlang/exercises/complex-numbers/rebar.config +30 -0
- data/tracks/erlang/exercises/complex-numbers/src/complex_numbers.app.src +9 -0
- data/tracks/erlang/exercises/complex-numbers/src/complex_numbers.erl +29 -0
- data/tracks/erlang/exercises/complex-numbers/src/example.erl +44 -0
- data/tracks/erlang/exercises/complex-numbers/test/complex_numbers_tests.erl +152 -0
- data/tracks/erlang/testgen/src/tgen.erl +1 -1
- data/tracks/erlang/testgen/src/tgen_complex-numbers.erl +75 -0
- data/tracks/java/config.json +10 -5
- data/tracks/javascript/config.json +13 -0
- data/tracks/javascript/exercises/isbn-verifier/README.md +66 -0
- data/tracks/javascript/exercises/isbn-verifier/example.js +24 -0
- data/tracks/javascript/exercises/isbn-verifier/isbn-verifier.spec.js +68 -0
- data/tracks/perl6/config/maintainers.json +4 -4
- data/tracks/perl6/config.json +21 -21
- data/tracks/php/README.md +1 -0
- data/tracks/python/config/maintainers.json +3 -3
- data/tracks/python/exercises/alphametics/alphametics_test.py +6 -6
- data/tracks/python/exercises/queen-attack/queen_attack_test.py +60 -40
- data/tracks/sml/config.json +13 -2
- data/tracks/sml/exercises/flatten-array/{HINTS.md → .meta/hints.md} +0 -0
- data/tracks/sml/exercises/nth-prime/{HINTS.md → .meta/hints.md} +0 -0
- data/tracks/sml/exercises/pig-latin/README.md +54 -0
- data/tracks/sml/exercises/pig-latin/example.sml +23 -0
- data/tracks/sml/exercises/pig-latin/pig-latin.sml +2 -0
- data/tracks/sml/exercises/pig-latin/test.sml +90 -0
- data/tracks/sml/exercises/pig-latin/testlib.sml +159 -0
- data/tracks/typescript/config.json +16 -0
- data/tracks/typescript/exercises/ocr-numbers/README.md +110 -0
- data/tracks/typescript/exercises/ocr-numbers/ocr-numbers.example.ts +92 -0
- data/tracks/typescript/exercises/ocr-numbers/ocr-numbers.test.ts +155 -0
- data/tracks/typescript/exercises/ocr-numbers/ocr-numbers.ts +3 -0
- data/tracks/typescript/exercises/ocr-numbers/package.json +36 -0
- data/tracks/typescript/exercises/ocr-numbers/tsconfig.json +22 -0
- data/tracks/typescript/exercises/ocr-numbers/tslint.json +127 -0
- data/tracks/typescript/exercises/ocr-numbers/yarn.lock +2624 -0
- metadata +55 -8
- data/tracks/ecmascript/exercises/transpose/README.md +0 -94
- data/tracks/ecmascript/exercises/transpose/example.js +0 -12
- data/tracks/ecmascript/exercises/transpose/transpose.spec.js +0 -67
@@ -0,0 +1,216 @@
|
|
1
|
+
import ComplexNumber from './complex-numbers.js';
|
2
|
+
|
3
|
+
describe('Complex numbers', () => {
|
4
|
+
test('Real part of a purely real number', () => {
|
5
|
+
const expected = 1;
|
6
|
+
const actual = new ComplexNumber(1, 0).real;
|
7
|
+
|
8
|
+
expect(actual).toEqual(expected);
|
9
|
+
});
|
10
|
+
|
11
|
+
xtest('Real part of a purely imaginary number', () => {
|
12
|
+
const expected = 0;
|
13
|
+
const actual = new ComplexNumber(0, 1).real;
|
14
|
+
|
15
|
+
expect(actual).toEqual(expected);
|
16
|
+
});
|
17
|
+
|
18
|
+
xtest('Real part of a number with real and imaginary part', () => {
|
19
|
+
const expected = 1;
|
20
|
+
const actual = new ComplexNumber(1, 2).real;
|
21
|
+
|
22
|
+
expect(actual).toEqual(expected);
|
23
|
+
});
|
24
|
+
|
25
|
+
xtest('Imaginary part of a purely real number', () => {
|
26
|
+
const expected = 0;
|
27
|
+
const actual = new ComplexNumber(1, 0).imag;
|
28
|
+
|
29
|
+
expect(actual).toEqual(expected);
|
30
|
+
});
|
31
|
+
|
32
|
+
xtest('Imaginary part of a purely imaginary number', () => {
|
33
|
+
const expected = 1;
|
34
|
+
const actual = new ComplexNumber(0, 1).imag;
|
35
|
+
|
36
|
+
expect(actual).toEqual(expected);
|
37
|
+
});
|
38
|
+
|
39
|
+
xtest('Imaginary part of a number with real and imaginary part', () => {
|
40
|
+
const expected = 2;
|
41
|
+
const actual = new ComplexNumber(1, 2).imag;
|
42
|
+
|
43
|
+
expect(actual).toEqual(expected);
|
44
|
+
});
|
45
|
+
|
46
|
+
xtest('Add purely real numbers', () => {
|
47
|
+
const expected = new ComplexNumber(3, 0);
|
48
|
+
const actual = new ComplexNumber(1, 0).add(new ComplexNumber(2, 0));
|
49
|
+
|
50
|
+
expect(actual).toEqual(expected);
|
51
|
+
});
|
52
|
+
|
53
|
+
xtest('Add purely imaginary numbers', () => {
|
54
|
+
const expected = new ComplexNumber(0, 3);
|
55
|
+
const actual = new ComplexNumber(0, 1).add(new ComplexNumber(0, 2));
|
56
|
+
|
57
|
+
expect(actual).toEqual(expected);
|
58
|
+
});
|
59
|
+
|
60
|
+
xtest('Add numbers with real and imaginary part', () => {
|
61
|
+
const expected = new ComplexNumber(4, 6);
|
62
|
+
const actual = new ComplexNumber(1, 2).add(new ComplexNumber(3, 4));
|
63
|
+
|
64
|
+
expect(actual).toEqual(expected);
|
65
|
+
});
|
66
|
+
|
67
|
+
xtest('Subtract purely real numbers', () => {
|
68
|
+
const expected = new ComplexNumber(-1, 0);
|
69
|
+
const actual = new ComplexNumber(1, 0).sub(new ComplexNumber(2, 0));
|
70
|
+
|
71
|
+
expect(actual).toEqual(expected);
|
72
|
+
});
|
73
|
+
|
74
|
+
xtest('Subtract purely imaginary numbers', () => {
|
75
|
+
const expected = new ComplexNumber(0, -1);
|
76
|
+
const actual = new ComplexNumber(0, 1).sub(new ComplexNumber(0, 2));
|
77
|
+
|
78
|
+
expect(actual).toEqual(expected);
|
79
|
+
});
|
80
|
+
|
81
|
+
xtest('Subtract numbers with real and imaginary part', () => {
|
82
|
+
const expected = new ComplexNumber(-2, -2);
|
83
|
+
const actual = new ComplexNumber(1, 2).sub(new ComplexNumber(3, 4));
|
84
|
+
|
85
|
+
expect(actual).toEqual(expected);
|
86
|
+
});
|
87
|
+
|
88
|
+
xtest('Multiply purely real numbers', () => {
|
89
|
+
const expected = new ComplexNumber(2, 0);
|
90
|
+
const actual = new ComplexNumber(1, 0).mul(new ComplexNumber(2, 0));
|
91
|
+
|
92
|
+
expect(actual).toEqual(expected);
|
93
|
+
});
|
94
|
+
|
95
|
+
xtest('Multiply imaginary unit', () => {
|
96
|
+
const expected = new ComplexNumber(-1, 0);
|
97
|
+
const actual = new ComplexNumber(0, 1).mul(new ComplexNumber(0, 1));
|
98
|
+
|
99
|
+
expect(actual).toEqual(expected);
|
100
|
+
});
|
101
|
+
|
102
|
+
xtest('Multiply purely imaginary numbers', () => {
|
103
|
+
const expected = new ComplexNumber(-2, 0);
|
104
|
+
const actual = new ComplexNumber(0, 1).mul(new ComplexNumber(0, 2));
|
105
|
+
|
106
|
+
expect(actual).toEqual(expected);
|
107
|
+
});
|
108
|
+
|
109
|
+
xtest('Multiply numbers with real and imaginary part', () => {
|
110
|
+
const expected = new ComplexNumber(-5, 10);
|
111
|
+
const actual = new ComplexNumber(1, 2).mul(new ComplexNumber(3, 4));
|
112
|
+
|
113
|
+
expect(actual).toEqual(expected);
|
114
|
+
});
|
115
|
+
|
116
|
+
xtest('Divide purely real numbers', () => {
|
117
|
+
const expected = new ComplexNumber(0.5, 0);
|
118
|
+
const actual = new ComplexNumber(1, 0).div(new ComplexNumber(2, 0));
|
119
|
+
|
120
|
+
expect(actual).toEqual(expected);
|
121
|
+
});
|
122
|
+
|
123
|
+
xtest('Divide purely imaginary numbers', () => {
|
124
|
+
const expected = new ComplexNumber(0.5, 0);
|
125
|
+
const actual = new ComplexNumber(0, 1).div(new ComplexNumber(0, 2));
|
126
|
+
|
127
|
+
expect(actual).toEqual(expected);
|
128
|
+
});
|
129
|
+
|
130
|
+
xtest('Divide numbers with real and imaginary part', () => {
|
131
|
+
const expected = new ComplexNumber(0.44, 0.08);
|
132
|
+
const actual = new ComplexNumber(1, 2).div(new ComplexNumber(3, 4));
|
133
|
+
|
134
|
+
expect(actual).toEqual(expected);
|
135
|
+
});
|
136
|
+
|
137
|
+
xtest('Absolute value of a positive purely real number', () => {
|
138
|
+
const expected = 5;
|
139
|
+
const actual = new ComplexNumber(5, 0).abs;
|
140
|
+
|
141
|
+
expect(actual).toEqual(expected);
|
142
|
+
});
|
143
|
+
|
144
|
+
xtest('Absolute value of a negative purely real number', () => {
|
145
|
+
const expected = 5;
|
146
|
+
const actual = new ComplexNumber(-5, 0).abs;
|
147
|
+
|
148
|
+
expect(actual).toEqual(expected);
|
149
|
+
});
|
150
|
+
|
151
|
+
xtest('Absolute value of a purely imaginary number with positive imaginary part', () => {
|
152
|
+
const expected = 5;
|
153
|
+
const actual = new ComplexNumber(0, 5).abs;
|
154
|
+
|
155
|
+
expect(actual).toEqual(expected);
|
156
|
+
});
|
157
|
+
|
158
|
+
xtest('Absolute value of a purely imaginary number with negative imaginary part', () => {
|
159
|
+
const expected = 5;
|
160
|
+
const actual = new ComplexNumber(0, -5).abs;
|
161
|
+
|
162
|
+
expect(actual).toEqual(expected);
|
163
|
+
});
|
164
|
+
|
165
|
+
xtest('Absolute value of a number with real and imaginary part', () => {
|
166
|
+
const expected = 5;
|
167
|
+
const actual = new ComplexNumber(3, 4).abs;
|
168
|
+
|
169
|
+
expect(actual).toEqual(expected);
|
170
|
+
});
|
171
|
+
|
172
|
+
xtest('Conjugate a purely real number', () => {
|
173
|
+
const expected = new ComplexNumber(5, 0);
|
174
|
+
const actual = new ComplexNumber(5, 0).conj;
|
175
|
+
|
176
|
+
expect(actual).toEqual(expected);
|
177
|
+
});
|
178
|
+
|
179
|
+
xtest('Conjugate a purely imaginary number', () => {
|
180
|
+
const expected = new ComplexNumber(0, -5);
|
181
|
+
const actual = new ComplexNumber(0, 5).conj;
|
182
|
+
|
183
|
+
expect(actual).toEqual(expected);
|
184
|
+
});
|
185
|
+
|
186
|
+
xtest('Conjugate a number with real and imaginary part', () => {
|
187
|
+
const expected = new ComplexNumber(1, -1);
|
188
|
+
const actual = new ComplexNumber(1, 1).conj;
|
189
|
+
|
190
|
+
expect(actual).toEqual(expected);
|
191
|
+
});
|
192
|
+
|
193
|
+
xtest('Euler\'s identity/formula', () => {
|
194
|
+
const expected = new ComplexNumber(-1, 0);
|
195
|
+
const actual = new ComplexNumber(0, Math.PI).exp;
|
196
|
+
|
197
|
+
expect(actual.real).toBeCloseTo(expected.real);
|
198
|
+
expect(actual.imag).toBeCloseTo(expected.imag);
|
199
|
+
});
|
200
|
+
|
201
|
+
xtest('Exponential of 0', () => {
|
202
|
+
const expected = new ComplexNumber(1, 0);
|
203
|
+
const actual = new ComplexNumber(0, 0).exp;
|
204
|
+
|
205
|
+
expect(actual.real).toBeCloseTo(expected.real);
|
206
|
+
expect(actual.imag).toBeCloseTo(expected.imag);
|
207
|
+
});
|
208
|
+
|
209
|
+
xtest('Exponential of a purely real number', () => {
|
210
|
+
const expected = new ComplexNumber(Math.E, 0);
|
211
|
+
const actual = new ComplexNumber(1, 0).exp;
|
212
|
+
|
213
|
+
expect(actual.real).toBeCloseTo(expected.real);
|
214
|
+
expect(actual.imag).toBeCloseTo(expected.imag);
|
215
|
+
});
|
216
|
+
});
|
@@ -0,0 +1,43 @@
|
|
1
|
+
export default class ComplexNumber {
|
2
|
+
|
3
|
+
constructor(real, imag) {
|
4
|
+
this.real = real;
|
5
|
+
this.imag = imag;
|
6
|
+
}
|
7
|
+
|
8
|
+
add(other) {
|
9
|
+
return new ComplexNumber(this.real + other.real, this.imag + other.imag);
|
10
|
+
}
|
11
|
+
|
12
|
+
sub(other) {
|
13
|
+
return new ComplexNumber(this.real - other.real, this.imag - other.imag);
|
14
|
+
}
|
15
|
+
|
16
|
+
mul(other) {
|
17
|
+
return new ComplexNumber(
|
18
|
+
(this.real * other.real) - (this.imag * other.imag),
|
19
|
+
(this.imag * other.real) + (this.real * other.imag));
|
20
|
+
}
|
21
|
+
|
22
|
+
div(other) {
|
23
|
+
return new ComplexNumber(
|
24
|
+
((this.real * other.real) + (this.imag * other.imag))
|
25
|
+
/ ((other.real * other.real) + (other.imag * other.imag)),
|
26
|
+
((this.imag * other.real) - (this.real * other.imag))
|
27
|
+
/ ((other.real * other.real) + (other.imag * other.imag)));
|
28
|
+
}
|
29
|
+
|
30
|
+
get abs() {
|
31
|
+
return Math.sqrt((this.real * this.real) + (this.imag * this.imag));
|
32
|
+
}
|
33
|
+
|
34
|
+
get conj() {
|
35
|
+
return new ComplexNumber(this.real, this.imag !== 0 ? -this.imag : 0);
|
36
|
+
}
|
37
|
+
|
38
|
+
get exp() {
|
39
|
+
return new ComplexNumber(
|
40
|
+
Math.exp(this.real) * Math.cos(this.imag),
|
41
|
+
Math.exp(this.real) * Math.sin(this.imag));
|
42
|
+
}
|
43
|
+
}
|
@@ -9,7 +9,7 @@
|
|
9
9
|
"url": "https://github.com/exercism/xecmascript"
|
10
10
|
},
|
11
11
|
"devDependencies": {
|
12
|
-
"babel-jest": "^
|
12
|
+
"babel-jest": "^21.2.0",
|
13
13
|
"babel-plugin-transform-builtin-extend": "^1.1.2",
|
14
14
|
"babel-preset-env": "^1.4.0",
|
15
15
|
"eslint": "^3.19.0",
|
@@ -17,7 +17,7 @@
|
|
17
17
|
"eslint-plugin-import": "^2.2.0",
|
18
18
|
"eslint-plugin-jsx-a11y": "^5.0.1",
|
19
19
|
"eslint-plugin-react": "^7.0.1",
|
20
|
-
"jest": "^
|
20
|
+
"jest": "^21.2.1"
|
21
21
|
},
|
22
22
|
"jest": {
|
23
23
|
"modulePathIgnorePatterns": [
|
data/tracks/elixir/config.json
CHANGED
@@ -783,10 +783,31 @@
|
|
783
783
|
],
|
784
784
|
"unlocked_by": null,
|
785
785
|
"uuid": "ce270a34-add1-422c-bb86-53b310f05e27"
|
786
|
+
},
|
787
|
+
{
|
788
|
+
"core": false,
|
789
|
+
"difficulty": 3,
|
790
|
+
"slug": "isbn-verifier",
|
791
|
+
"topics": [
|
792
|
+
"string_processing"
|
793
|
+
],
|
794
|
+
"unlocked_by": null,
|
795
|
+
"uuid": "0fb09d01-1f8b-4654-9004-52baa057412e"
|
796
|
+
},
|
797
|
+
{
|
798
|
+
"core": false,
|
799
|
+
"difficulty": 4,
|
800
|
+
"slug": "spiral-matrix",
|
801
|
+
"topics": [
|
802
|
+
"lists",
|
803
|
+
"transforming"
|
804
|
+
],
|
805
|
+
"unlocked_by": null,
|
806
|
+
"uuid": "b0216103-000b-8480-556d-816ddca02c40810d1e9"
|
786
807
|
}
|
787
808
|
],
|
788
809
|
"foregone": [
|
789
810
|
"robot-name"
|
790
811
|
],
|
791
812
|
"language": "Elixir"
|
792
|
-
}
|
813
|
+
}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# ISBN-Verifier
|
2
|
+
|
3
|
+
Check if a given ISBN-10 is valid.
|
4
|
+
|
5
|
+
## Functionality
|
6
|
+
|
7
|
+
Given an unknown string the program should check if the provided string is a valid ISBN-10.
|
8
|
+
Putting this into place requires some thinking about preprocessing/parsing of the string prior to calculating the check digit for the ISBN.
|
9
|
+
|
10
|
+
The program should allow for ISBN-10 without the separating dashes to be verified as well.
|
11
|
+
|
12
|
+
## ISBN
|
13
|
+
|
14
|
+
Let's take a random ISBN-10 number, say `3-598-21508-8` for this.
|
15
|
+
The first digit block indicates the group where the ISBN belongs. Groups can consist of shared languages, geographic regions or countries. The leading '3' signals this ISBN is from a german speaking country.
|
16
|
+
The following number block is to identify the publisher. Since this is a three digit publisher number there is a 5 digit title number for this book.
|
17
|
+
The last digit in the ISBN is the check digit which is used to detect read errors.
|
18
|
+
|
19
|
+
The first 9 digits in the ISBN have to be between 0 and 9.
|
20
|
+
The check digit can additionally be an 'X' to allow 10 to be a valid check digit as well.
|
21
|
+
|
22
|
+
A valid ISBN-10 is calculated with this formula `(x1 * 10 + x2 * 9 + x3 * 8 + x4 * 7 + x5 * 6 + x6 * 5 + x7 * 4 + x8 * 3 + x9 * 2 + x10 * 1) mod 11 == 0`
|
23
|
+
So for our example ISBN this means:
|
24
|
+
(3 * 10 + 5 * 9 + 9 * 8 + 8 * 7 + 2 * 6 + 1 * 5 + 5 * 4 + 0 * 3 + 8 * 2 + 8 * 1) mod 11 = 0
|
25
|
+
|
26
|
+
Which proves that the ISBN is valid.
|
27
|
+
|
28
|
+
## Caveats
|
29
|
+
|
30
|
+
Converting from string to number can be tricky in certain languages.
|
31
|
+
It's getting even trickier since the check-digit of an ISBN-10 can be 'X'.
|
32
|
+
|
33
|
+
## Bonus tasks
|
34
|
+
|
35
|
+
* Generate a valid ISBN-13 from the input ISBN-10 (and maybe verify it again with a derived verifier)
|
36
|
+
|
37
|
+
* Generate valid ISBN, maybe even from a given starting ISBN
|
38
|
+
|
39
|
+
|
40
|
+
## Running tests
|
41
|
+
|
42
|
+
Execute the tests with:
|
43
|
+
|
44
|
+
```bash
|
45
|
+
$ elixir isbn_verifier_test.exs
|
46
|
+
```
|
47
|
+
|
48
|
+
|
49
|
+
### Pending tests
|
50
|
+
|
51
|
+
In the test suites, all but the first test have been skipped.
|
52
|
+
|
53
|
+
Once you get a test passing, you can unskip the next one by
|
54
|
+
commenting out the relevant `@tag :pending` with a `#` symbol.
|
55
|
+
|
56
|
+
For example:
|
57
|
+
|
58
|
+
```elixir
|
59
|
+
# @tag :pending
|
60
|
+
test "shouting" do
|
61
|
+
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
Or, you can enable all the tests by commenting out the
|
66
|
+
`ExUnit.configure` line in the test suite.
|
67
|
+
|
68
|
+
```elixir
|
69
|
+
# ExUnit.configure exclude: :pending, trace: true
|
70
|
+
```
|
71
|
+
|
72
|
+
For more detailed information about the Elixir track, please
|
73
|
+
see the [help page](http://exercism.io/languages/elixir).
|
74
|
+
|
75
|
+
## Source
|
76
|
+
|
77
|
+
Converting a string into a number and some basic processing utilizing a relatable real world example. [https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation](https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation)
|
78
|
+
|
79
|
+
## Submitting Incomplete Solutions
|
80
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,36 @@
|
|
1
|
+
defmodule ISBNVerifier do
|
2
|
+
@doc """
|
3
|
+
Checks if a string is a valid ISBN-10 identifier
|
4
|
+
|
5
|
+
## Examples
|
6
|
+
|
7
|
+
iex> ISBNVerifier.isbn?("3-598-21507-X")
|
8
|
+
true
|
9
|
+
|
10
|
+
iex> ISBNVerifier.isbn?("3-598-2K507-0")
|
11
|
+
false
|
12
|
+
|
13
|
+
"""
|
14
|
+
@spec isbn?(String.t()) :: boolean
|
15
|
+
def isbn?(isbn) do
|
16
|
+
if Regex.match?(~r/^(\d-?){9}(\d|X)$/, isbn) do
|
17
|
+
checksum =
|
18
|
+
isbn
|
19
|
+
|> String.replace("-", "")
|
20
|
+
|> String.graphemes()
|
21
|
+
|> Enum.zip(10..1)
|
22
|
+
|> Enum.map(&checksum_weighting/1)
|
23
|
+
|> Enum.sum()
|
24
|
+
|
25
|
+
rem(checksum, 11) == 0
|
26
|
+
else
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
defp checksum_weighting({"X", 1}), do: 10
|
32
|
+
|
33
|
+
defp checksum_weighting({digit, weight}) do
|
34
|
+
String.to_integer(digit) * weight
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
defmodule ISBNVerifier do
|
2
|
+
@doc """
|
3
|
+
Checks if a string is a valid ISBN-10 identifier
|
4
|
+
|
5
|
+
## Examples
|
6
|
+
|
7
|
+
iex> ISBNVerifier.isbn?("3-598-21507-X")
|
8
|
+
true
|
9
|
+
|
10
|
+
iex> ISBNVerifier.isbn?("3-598-2K507-0")
|
11
|
+
false
|
12
|
+
|
13
|
+
"""
|
14
|
+
@spec isbn?(String.t()) :: boolean
|
15
|
+
def isbn?(isbn) do
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
2
|
+
Code.load_file("isbn_verifier.exs", __DIR__)
|
3
|
+
end
|
4
|
+
|
5
|
+
ExUnit.start()
|
6
|
+
ExUnit.configure(exclude: :pending, trace: true)
|
7
|
+
|
8
|
+
defmodule ISBNVerifierTest do
|
9
|
+
use ExUnit.Case
|
10
|
+
|
11
|
+
#@tag :pending
|
12
|
+
test "valid isbn number" do
|
13
|
+
assert ISBNVerifier.isbn?("3-598-21508-8")
|
14
|
+
end
|
15
|
+
|
16
|
+
@tag :pending
|
17
|
+
test "invalid isbn check digit" do
|
18
|
+
refute ISBNVerifier.isbn?("3-598-21508-9")
|
19
|
+
end
|
20
|
+
|
21
|
+
@tag :pending
|
22
|
+
test "valid isbn number with a check digit of 10" do
|
23
|
+
assert ISBNVerifier.isbn?("3-598-21507-X")
|
24
|
+
end
|
25
|
+
|
26
|
+
@tag :pending
|
27
|
+
test "check digit is a character other than X" do
|
28
|
+
refute ISBNVerifier.isbn?("3-598-21507-A")
|
29
|
+
end
|
30
|
+
|
31
|
+
@tag :pending
|
32
|
+
test "invalid character in isbn" do
|
33
|
+
refute ISBNVerifier.isbn?("3-598-2K507-0")
|
34
|
+
end
|
35
|
+
|
36
|
+
@tag :pending
|
37
|
+
test "X is only valid as a check digit" do
|
38
|
+
refute ISBNVerifier.isbn?("3-598-2X507-0")
|
39
|
+
end
|
40
|
+
|
41
|
+
@tag :pending
|
42
|
+
test "valid isbn without separating dashes" do
|
43
|
+
assert ISBNVerifier.isbn?("3598215088")
|
44
|
+
end
|
45
|
+
|
46
|
+
@tag :pending
|
47
|
+
test "isbn without separating dashes and X as check digit" do
|
48
|
+
assert ISBNVerifier.isbn?("359821507X")
|
49
|
+
end
|
50
|
+
|
51
|
+
@tag :pending
|
52
|
+
test "isbn without check digit and dashes" do
|
53
|
+
refute ISBNVerifier.isbn?("359821507")
|
54
|
+
end
|
55
|
+
|
56
|
+
@tag :pending
|
57
|
+
test "too long isbn and no dashes" do
|
58
|
+
refute ISBNVerifier.isbn?("3598215078X")
|
59
|
+
end
|
60
|
+
|
61
|
+
@tag :pending
|
62
|
+
test "isbn without check digit" do
|
63
|
+
refute ISBNVerifier.isbn?("3-598-21507")
|
64
|
+
end
|
65
|
+
|
66
|
+
@tag :pending
|
67
|
+
test "too long isbn" do
|
68
|
+
refute ISBNVerifier.isbn?("3-598-21507-XA")
|
69
|
+
end
|
70
|
+
|
71
|
+
@tag :pending
|
72
|
+
test "check digit of X should not be used for 0" do
|
73
|
+
refute ISBNVerifier.isbn?("3-598-21515-X")
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Spiral Matrix
|
2
|
+
|
3
|
+
Given the size, return a square matrix of numbers in spiral order.
|
4
|
+
|
5
|
+
The matrix should be filled with natural numbers, starting from 1
|
6
|
+
in the top-left corner, increasing in an inward, clockwise spiral order,
|
7
|
+
like these examples:
|
8
|
+
|
9
|
+
###### Spiral matrix of size 3
|
10
|
+
|
11
|
+
```text
|
12
|
+
1 2 3
|
13
|
+
8 9 4
|
14
|
+
7 6 5
|
15
|
+
```
|
16
|
+
|
17
|
+
###### Spiral matrix of size 4
|
18
|
+
|
19
|
+
```text
|
20
|
+
1 2 3 4
|
21
|
+
12 13 14 5
|
22
|
+
11 16 15 6
|
23
|
+
10 9 8 7
|
24
|
+
```
|
25
|
+
|
26
|
+
## Running tests
|
27
|
+
|
28
|
+
Execute the tests with:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
$ elixir spiral_matrix_test.exs
|
32
|
+
```
|
33
|
+
|
34
|
+
### Pending tests
|
35
|
+
|
36
|
+
In the test suites, all but the first test have been skipped.
|
37
|
+
|
38
|
+
Once you get a test passing, you can unskip the next one by
|
39
|
+
commenting out the relevant `@tag :pending` with a `#` symbol.
|
40
|
+
|
41
|
+
For example:
|
42
|
+
|
43
|
+
```elixir
|
44
|
+
# @tag :pending
|
45
|
+
test "shouting" do
|
46
|
+
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Or, you can enable all the tests by commenting out the
|
51
|
+
`ExUnit.configure` line in the test suite.
|
52
|
+
|
53
|
+
```elixir
|
54
|
+
# ExUnit.configure exclude: :pending, trace: true
|
55
|
+
```
|
56
|
+
|
57
|
+
For more detailed information about the Elixir track, please
|
58
|
+
see the [help page](http://exercism.io/languages/elixir).
|
59
|
+
|
60
|
+
## Source
|
61
|
+
|
62
|
+
Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension. [spiral ascension](https://www.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/)
|
63
|
+
|
64
|
+
## Submitting Incomplete Solutions
|
65
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
defmodule Spiral do
|
2
|
+
|
3
|
+
@doc """
|
4
|
+
Given the dimension, return a square matrix of numbers in clockwise spiral order.
|
5
|
+
"""
|
6
|
+
@spec matrix(dimension :: integer) :: list(list(integer))
|
7
|
+
def matrix(0), do: []
|
8
|
+
def matrix(dimension) do
|
9
|
+
unwind(dimension, dimension, 1)
|
10
|
+
end
|
11
|
+
|
12
|
+
defp unwind(row, col, start) do
|
13
|
+
case col do
|
14
|
+
0 -> [[]]
|
15
|
+
_ -> [Enum.to_list(start..start + col - 1) |
|
16
|
+
unwind(col, row - 1, start + col) |> rotate_right]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
defp rotate_right(matrix) do
|
21
|
+
matrix |> transpose |> Enum.map(&Enum.reverse/1)
|
22
|
+
end
|
23
|
+
|
24
|
+
defp transpose(matrix) do
|
25
|
+
matrix |> List.zip |> Enum.map(&Tuple.to_list/1)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
2
|
+
Code.load_file("spiral.exs", __DIR__)
|
3
|
+
end
|
4
|
+
|
5
|
+
ExUnit.start
|
6
|
+
ExUnit.configure trace: true, exclude: :pending
|
7
|
+
|
8
|
+
defmodule SpiralTest do
|
9
|
+
use ExUnit.Case
|
10
|
+
|
11
|
+
# @tag :pending
|
12
|
+
test "empty spiral" do
|
13
|
+
assert Spiral.matrix(0) == []
|
14
|
+
end
|
15
|
+
|
16
|
+
@tag :pending
|
17
|
+
test "trivial spiral" do
|
18
|
+
assert Spiral.matrix(1) == [ [1] ]
|
19
|
+
end
|
20
|
+
|
21
|
+
@tag :pending
|
22
|
+
test "spiral of side length 2" do
|
23
|
+
assert Spiral.matrix(2) == [
|
24
|
+
[1, 2],
|
25
|
+
[4, 3]
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
@tag :pending
|
30
|
+
test "spiral of side length 3" do
|
31
|
+
assert Spiral.matrix(3) == [
|
32
|
+
[1, 2, 3],
|
33
|
+
[8, 9, 4],
|
34
|
+
[7, 6, 5]
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
@tag :pending
|
39
|
+
test "spiral of side length 4" do
|
40
|
+
assert Spiral.matrix(4) == [
|
41
|
+
[ 1, 2, 3, 4],
|
42
|
+
[12, 13, 14, 5],
|
43
|
+
[11, 16, 15, 6],
|
44
|
+
[10, 9, 8, 7]
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
@tag :pending
|
49
|
+
test "spiral of size 5" do
|
50
|
+
assert Spiral.matrix(5) == [
|
51
|
+
[ 1, 2, 3, 4, 5],
|
52
|
+
[16, 17, 18, 19, 6],
|
53
|
+
[15, 24, 25, 20, 7],
|
54
|
+
[14, 23, 22, 21, 8],
|
55
|
+
[13, 12, 11, 10, 9]
|
56
|
+
]
|
57
|
+
end
|
58
|
+
end
|
data/tracks/erlang/config.json
CHANGED
@@ -322,6 +322,16 @@
|
|
322
322
|
|
323
323
|
]
|
324
324
|
},
|
325
|
+
{
|
326
|
+
"uuid": "5fc48c1b-0e1b-47b3-b30a-5281ec364aad",
|
327
|
+
"slug": "complex-numbers",
|
328
|
+
"core": false,
|
329
|
+
"unlocked_by": null,
|
330
|
+
"difficulty": 5,
|
331
|
+
"topics": [
|
332
|
+
|
333
|
+
]
|
334
|
+
},
|
325
335
|
{
|
326
336
|
"uuid": "8ad0c97b-189d-46ac-bb72-2c72f1fe4728",
|
327
337
|
"slug": "rotational-cipher",
|