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.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/problem-specifications/exercises/custom-set/canonical-data.json +8 -1
  4. data/tracks/c/README.md +2 -44
  5. data/tracks/c/docs/CONTRIBUTING.md +93 -0
  6. data/tracks/c/docs/C_STYLE_GUIDE.md +1 -1
  7. data/tracks/clojure/config.json +27 -0
  8. data/tracks/clojure/exercises/accumulate/project.clj +1 -1
  9. data/tracks/clojure/exercises/acronym/project.clj +1 -1
  10. data/tracks/clojure/exercises/all-your-base/project.clj +1 -1
  11. data/tracks/clojure/exercises/allergies/project.clj +1 -1
  12. data/tracks/clojure/exercises/anagram/project.clj +1 -1
  13. data/tracks/clojure/exercises/atbash-cipher/project.clj +1 -1
  14. data/tracks/clojure/exercises/bank-account/project.clj +1 -1
  15. data/tracks/clojure/exercises/beer-song/project.clj +1 -1
  16. data/tracks/clojure/exercises/binary/project.clj +1 -1
  17. data/tracks/clojure/exercises/binary-search/project.clj +1 -1
  18. data/tracks/clojure/exercises/binary-search-tree/project.clj +1 -1
  19. data/tracks/clojure/exercises/bob/project.clj +1 -1
  20. data/tracks/clojure/exercises/bracket-push/project.clj +1 -1
  21. data/tracks/clojure/exercises/change/project.clj +1 -1
  22. data/tracks/clojure/exercises/clock/project.clj +1 -1
  23. data/tracks/clojure/exercises/collatz-conjecture/project.clj +1 -1
  24. data/tracks/clojure/exercises/complex-numbers/project.clj +1 -1
  25. data/tracks/clojure/exercises/crypto-square/project.clj +1 -1
  26. data/tracks/clojure/exercises/diamond/README.md +51 -0
  27. data/tracks/clojure/exercises/diamond/project.clj +4 -0
  28. data/tracks/clojure/exercises/diamond/src/example.clj +22 -0
  29. data/tracks/clojure/exercises/diamond/test/diamond_test.clj +79 -0
  30. data/tracks/clojure/exercises/difference-of-squares/project.clj +1 -1
  31. data/tracks/clojure/exercises/etl/project.clj +1 -1
  32. data/tracks/clojure/exercises/flatten-array/project.clj +1 -1
  33. data/tracks/clojure/exercises/gigasecond/project.clj +1 -1
  34. data/tracks/clojure/exercises/grade-school/project.clj +1 -1
  35. data/tracks/clojure/exercises/grains/project.clj +1 -1
  36. data/tracks/clojure/exercises/hamming/project.clj +1 -1
  37. data/tracks/clojure/exercises/hello-world/project.clj +1 -1
  38. data/tracks/clojure/exercises/hexadecimal/project.clj +1 -1
  39. data/tracks/clojure/exercises/isogram/project.clj +1 -1
  40. data/tracks/clojure/exercises/kindergarten-garden/project.clj +1 -1
  41. data/tracks/clojure/exercises/largest-series-product/project.clj +1 -1
  42. data/tracks/clojure/exercises/leap/project.clj +1 -1
  43. data/tracks/clojure/exercises/luhn/project.clj +1 -1
  44. data/tracks/clojure/exercises/meetup/project.clj +1 -1
  45. data/tracks/clojure/exercises/minesweeper/project.clj +1 -1
  46. data/tracks/clojure/exercises/nth-prime/project.clj +1 -1
  47. data/tracks/clojure/exercises/nucleotide-count/project.clj +1 -1
  48. data/tracks/clojure/exercises/octal/project.clj +1 -1
  49. data/tracks/clojure/exercises/pascals-triangle/project.clj +1 -1
  50. data/tracks/clojure/exercises/perfect-numbers/project.clj +1 -1
  51. data/tracks/clojure/exercises/phone-number/project.clj +1 -1
  52. data/tracks/clojure/exercises/pig-latin/project.clj +1 -1
  53. data/tracks/clojure/exercises/prime-factors/project.clj +1 -1
  54. data/tracks/clojure/exercises/protein-translation/README.md +40 -0
  55. data/tracks/clojure/exercises/protein-translation/project.clj +4 -0
  56. data/tracks/clojure/exercises/protein-translation/src/example.clj +19 -0
  57. data/tracks/clojure/exercises/protein-translation/test/protein_translation_test.clj +36 -0
  58. data/tracks/clojure/exercises/queen-attack/project.clj +1 -1
  59. data/tracks/clojure/exercises/raindrops/project.clj +1 -1
  60. data/tracks/clojure/exercises/rna-transcription/project.clj +1 -1
  61. data/tracks/clojure/exercises/robot-name/project.clj +1 -1
  62. data/tracks/clojure/exercises/robot-simulator/project.clj +1 -1
  63. data/tracks/clojure/exercises/roman-numerals/project.clj +1 -1
  64. data/tracks/clojure/exercises/rotational-cipher/project.clj +1 -1
  65. data/tracks/clojure/exercises/run-length-encoding/README.md +36 -0
  66. data/tracks/clojure/exercises/run-length-encoding/project.clj +4 -0
  67. data/tracks/clojure/exercises/run-length-encoding/src/example.clj +20 -0
  68. data/tracks/clojure/exercises/run-length-encoding/src/run_length_encoding.clj +11 -0
  69. data/tracks/clojure/exercises/run-length-encoding/test/run_length_encoding_test.clj +57 -0
  70. data/tracks/clojure/exercises/scrabble-score/project.clj +1 -1
  71. data/tracks/clojure/exercises/secret-handshake/project.clj +1 -1
  72. data/tracks/clojure/exercises/series/project.clj +1 -1
  73. data/tracks/clojure/exercises/sieve/project.clj +1 -1
  74. data/tracks/clojure/exercises/space-age/project.clj +1 -1
  75. data/tracks/clojure/exercises/spiral-matrix/project.clj +1 -1
  76. data/tracks/clojure/exercises/strain/project.clj +1 -1
  77. data/tracks/clojure/exercises/sublist/project.clj +1 -1
  78. data/tracks/clojure/exercises/sum-of-multiples/project.clj +1 -1
  79. data/tracks/clojure/exercises/triangle/project.clj +1 -1
  80. data/tracks/clojure/exercises/trinary/project.clj +1 -1
  81. data/tracks/clojure/exercises/word-count/project.clj +1 -1
  82. data/tracks/clojure/exercises/wordy/project.clj +1 -1
  83. data/tracks/clojure/project.clj +2 -2
  84. data/tracks/ecmascript/config.json +10 -15
  85. data/tracks/ecmascript/docs/TESTS.md +15 -0
  86. data/tracks/ecmascript/exercises/complex-numbers/README.md +68 -0
  87. data/tracks/ecmascript/exercises/complex-numbers/complex-numbers.spec.js +216 -0
  88. data/tracks/ecmascript/exercises/complex-numbers/example.js +43 -0
  89. data/tracks/ecmascript/exercises/{transpose → complex-numbers}/package.json +2 -2
  90. data/tracks/elixir/config.json +22 -1
  91. data/tracks/elixir/exercises/isbn-verifier/README.md +80 -0
  92. data/tracks/elixir/exercises/isbn-verifier/example.exs +36 -0
  93. data/tracks/elixir/exercises/isbn-verifier/isbn_verifier.exs +18 -0
  94. data/tracks/elixir/exercises/isbn-verifier/isbn_verifier_test.exs +75 -0
  95. data/tracks/elixir/exercises/spiral-matrix/README.md +65 -0
  96. data/tracks/elixir/exercises/spiral-matrix/example.exs +27 -0
  97. data/tracks/elixir/exercises/spiral-matrix/spiral.exs +9 -0
  98. data/tracks/elixir/exercises/spiral-matrix/spiral_test.exs +58 -0
  99. data/tracks/erlang/config.json +10 -0
  100. data/tracks/erlang/exercises/complex-numbers/HINTS.md +2 -0
  101. data/tracks/erlang/exercises/complex-numbers/README.md +85 -0
  102. data/tracks/erlang/exercises/complex-numbers/include/exercism.hrl +11 -0
  103. data/tracks/erlang/exercises/complex-numbers/rebar.config +30 -0
  104. data/tracks/erlang/exercises/complex-numbers/src/complex_numbers.app.src +9 -0
  105. data/tracks/erlang/exercises/complex-numbers/src/complex_numbers.erl +29 -0
  106. data/tracks/erlang/exercises/complex-numbers/src/example.erl +44 -0
  107. data/tracks/erlang/exercises/complex-numbers/test/complex_numbers_tests.erl +152 -0
  108. data/tracks/erlang/testgen/src/tgen.erl +1 -1
  109. data/tracks/erlang/testgen/src/tgen_complex-numbers.erl +75 -0
  110. data/tracks/java/config.json +10 -5
  111. data/tracks/javascript/config.json +13 -0
  112. data/tracks/javascript/exercises/isbn-verifier/README.md +66 -0
  113. data/tracks/javascript/exercises/isbn-verifier/example.js +24 -0
  114. data/tracks/javascript/exercises/isbn-verifier/isbn-verifier.spec.js +68 -0
  115. data/tracks/perl6/config/maintainers.json +4 -4
  116. data/tracks/perl6/config.json +21 -21
  117. data/tracks/php/README.md +1 -0
  118. data/tracks/python/config/maintainers.json +3 -3
  119. data/tracks/python/exercises/alphametics/alphametics_test.py +6 -6
  120. data/tracks/python/exercises/queen-attack/queen_attack_test.py +60 -40
  121. data/tracks/sml/config.json +13 -2
  122. data/tracks/sml/exercises/flatten-array/{HINTS.md → .meta/hints.md} +0 -0
  123. data/tracks/sml/exercises/nth-prime/{HINTS.md → .meta/hints.md} +0 -0
  124. data/tracks/sml/exercises/pig-latin/README.md +54 -0
  125. data/tracks/sml/exercises/pig-latin/example.sml +23 -0
  126. data/tracks/sml/exercises/pig-latin/pig-latin.sml +2 -0
  127. data/tracks/sml/exercises/pig-latin/test.sml +90 -0
  128. data/tracks/sml/exercises/pig-latin/testlib.sml +159 -0
  129. data/tracks/typescript/config.json +16 -0
  130. data/tracks/typescript/exercises/ocr-numbers/README.md +110 -0
  131. data/tracks/typescript/exercises/ocr-numbers/ocr-numbers.example.ts +92 -0
  132. data/tracks/typescript/exercises/ocr-numbers/ocr-numbers.test.ts +155 -0
  133. data/tracks/typescript/exercises/ocr-numbers/ocr-numbers.ts +3 -0
  134. data/tracks/typescript/exercises/ocr-numbers/package.json +36 -0
  135. data/tracks/typescript/exercises/ocr-numbers/tsconfig.json +22 -0
  136. data/tracks/typescript/exercises/ocr-numbers/tslint.json +127 -0
  137. data/tracks/typescript/exercises/ocr-numbers/yarn.lock +2624 -0
  138. metadata +55 -8
  139. data/tracks/ecmascript/exercises/transpose/README.md +0 -94
  140. data/tracks/ecmascript/exercises/transpose/example.js +0 -12
  141. 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": "^20.0.3",
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.0.4"
20
+ "jest": "^21.2.1"
21
21
  },
22
22
  "jest": {
23
23
  "modulePathIgnorePatterns": [
@@ -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,9 @@
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(dimension) do
8
+ end
9
+ 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
@@ -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",