trackler 2.1.0.0 → 2.1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/connect/description.md +2 -1
  3. data/common/exercises/crypto-square/canonical-data.json +2 -2
  4. data/common/exercises/two-bucket/canonical-data.json +27 -1
  5. data/lib/trackler/version.rb +1 -1
  6. data/tracks/c/exercises/perfect-numbers/src/example.c +8 -4
  7. data/tracks/clojure/config.json +5 -0
  8. data/tracks/clojure/exercises/secret-handshake/project.clj +4 -0
  9. data/tracks/clojure/exercises/secret-handshake/src/example.clj +19 -0
  10. data/tracks/clojure/exercises/secret-handshake/test/secret_handshake_test.clj +55 -0
  11. data/tracks/cpp/.travis.yml +4 -3
  12. data/tracks/cpp/README.md +1 -1
  13. data/tracks/cpp/config.json +171 -67
  14. data/tracks/cpp/docs/ABOUT.md +2 -2
  15. data/tracks/cpp/docs/INSTALLATION.md +22 -28
  16. data/tracks/cpp/docs/TESTS.md +1 -1
  17. data/tracks/cpp/exercises/anagram/CMakeLists.txt +2 -9
  18. data/tracks/cpp/exercises/beer-song/CMakeLists.txt +2 -9
  19. data/tracks/cpp/exercises/binary/CMakeLists.txt +2 -9
  20. data/tracks/cpp/exercises/bob/CMakeLists.txt +2 -9
  21. data/tracks/cpp/exercises/clock/CMakeLists.txt +2 -9
  22. data/tracks/cpp/exercises/clock/clock_test.cpp +188 -64
  23. data/tracks/cpp/exercises/clock/example.cpp +17 -12
  24. data/tracks/cpp/exercises/clock/example.h +1 -0
  25. data/tracks/cpp/exercises/crypto-square/CMakeLists.txt +2 -9
  26. data/tracks/cpp/exercises/difference-of-squares/CMakeLists.txt +2 -9
  27. data/tracks/cpp/exercises/etl/CMakeLists.txt +2 -9
  28. data/tracks/cpp/exercises/etl/etl_test.cpp +5 -5
  29. data/tracks/cpp/exercises/food-chain/CMakeLists.txt +2 -9
  30. data/tracks/cpp/exercises/gigasecond/CMakeLists.txt +2 -9
  31. data/tracks/cpp/exercises/gigasecond/example.cpp +2 -6
  32. data/tracks/cpp/exercises/gigasecond/example.h +2 -2
  33. data/tracks/cpp/exercises/gigasecond/gigasecond_test.cpp +26 -8
  34. data/tracks/cpp/exercises/grade-school/CMakeLists.txt +2 -9
  35. data/tracks/cpp/exercises/grade-school/grade_school_test.cpp +5 -6
  36. data/tracks/cpp/exercises/grains/CMakeLists.txt +2 -9
  37. data/tracks/cpp/exercises/hamming/CMakeLists.txt +2 -9
  38. data/tracks/cpp/exercises/hello-world/CMakeLists.txt +2 -9
  39. data/tracks/cpp/exercises/hexadecimal/CMakeLists.txt +2 -9
  40. data/tracks/cpp/exercises/leap/CMakeLists.txt +2 -9
  41. data/tracks/cpp/exercises/meetup/CMakeLists.txt +2 -9
  42. data/tracks/cpp/exercises/meetup/meetup_test.cpp +1 -1
  43. data/tracks/cpp/exercises/nth-prime/CMakeLists.txt +2 -9
  44. data/tracks/cpp/exercises/nucleotide-count/CMakeLists.txt +2 -9
  45. data/tracks/cpp/exercises/nucleotide-count/nucleotide_count_test.cpp +3 -4
  46. data/tracks/cpp/exercises/phone-number/CMakeLists.txt +2 -9
  47. data/tracks/cpp/exercises/prime-factors/CMakeLists.txt +2 -9
  48. data/tracks/cpp/exercises/queen-attack/CMakeLists.txt +2 -9
  49. data/tracks/cpp/exercises/raindrops/CMakeLists.txt +2 -9
  50. data/tracks/cpp/exercises/rna-transcription/CMakeLists.txt +2 -9
  51. data/tracks/cpp/exercises/robot-name/CMakeLists.txt +2 -9
  52. data/tracks/cpp/exercises/roman-numerals/CMakeLists.txt +2 -9
  53. data/tracks/cpp/exercises/say/CMakeLists.txt +2 -9
  54. data/tracks/cpp/exercises/scrabble-score/CMakeLists.txt +2 -9
  55. data/tracks/cpp/exercises/series/CMakeLists.txt +2 -9
  56. data/tracks/cpp/exercises/series/series_test.cpp +11 -11
  57. data/tracks/cpp/exercises/sieve/CMakeLists.txt +2 -9
  58. data/tracks/cpp/exercises/space-age/CMakeLists.txt +2 -9
  59. data/tracks/cpp/exercises/sum-of-multiples/CMakeLists.txt +2 -9
  60. data/tracks/cpp/exercises/triangle/CMakeLists.txt +2 -9
  61. data/tracks/cpp/exercises/trinary/CMakeLists.txt +2 -9
  62. data/tracks/cpp/exercises/word-count/CMakeLists.txt +2 -9
  63. data/tracks/cpp/exercises/word-count/word_count_test.cpp +14 -15
  64. data/tracks/go/README.md +27 -13
  65. data/tracks/go/config.json +1 -0
  66. data/tracks/go/exercises/connect/.meta/gen.go +1 -3
  67. data/tracks/go/exercises/connect/cases_test.go +2 -1
  68. data/tracks/go/exercises/custom-set/.meta/gen.go +122 -101
  69. data/tracks/go/exercises/custom-set/cases_test.go +13 -4
  70. data/tracks/go/exercises/custom-set/custom_set_test.go +2 -2
  71. data/tracks/go/exercises/hamming/.meta/gen.go +1 -3
  72. data/tracks/go/exercises/hamming/cases_test.go +7 -1
  73. data/tracks/go/exercises/hamming/example.go +1 -1
  74. data/tracks/go/exercises/hamming/hamming_test.go +1 -1
  75. data/tracks/go/exercises/hello-world/{hello_example_test.go → example_helloworld_test.go} +0 -0
  76. data/tracks/go/exercises/house/house_test.go +8 -8
  77. data/tracks/go/exercises/meetup/.meta/gen.go +1 -3
  78. data/tracks/go/exercises/meetup/cases_test.go +2 -1
  79. data/tracks/go/exercises/palindrome-products/example.go +1 -1
  80. data/tracks/go/exercises/palindrome-products/palindrome_products_test.go +1 -1
  81. data/tracks/go/exercises/pascals-triangle/pascals_triangle_test.go +24 -4
  82. data/tracks/go/exercises/rna-transcription/.meta/gen.go +1 -3
  83. data/tracks/go/exercises/rna-transcription/cases_test.go +2 -1
  84. data/tracks/go/exercises/roman-numerals/.meta/gen.go +1 -3
  85. data/tracks/go/exercises/roman-numerals/cases_test.go +2 -1
  86. data/tracks/go/exercises/roman-numerals/example.go +1 -1
  87. data/tracks/go/exercises/transpose/.meta/gen.go +1 -3
  88. data/tracks/go/exercises/transpose/cases_test.go +2 -1
  89. data/tracks/go/exercises/transpose/transpose_test.go +5 -0
  90. data/tracks/go/exercises/word-count/.meta/gen.go +1 -3
  91. data/tracks/go/exercises/word-count/cases_test.go +2 -1
  92. data/tracks/go/gen/gen.go +3 -2
  93. data/tracks/java/config.json +5 -0
  94. data/tracks/java/exercises/saddle-points/build.gradle +17 -0
  95. data/tracks/java/exercises/saddle-points/src/example/java/Matrix.java +44 -0
  96. data/tracks/java/exercises/saddle-points/src/example/java/MatrixCoordinate.java +31 -0
  97. data/tracks/java/exercises/saddle-points/src/main/java/Matrix.java +5 -0
  98. data/tracks/java/exercises/saddle-points/src/main/java/MatrixCoordinate.java +31 -0
  99. data/tracks/java/exercises/saddle-points/src/test/java/MatrixTest.java +82 -0
  100. data/tracks/java/exercises/settings.gradle +1 -0
  101. data/tracks/javascript/.travis.yml +3 -1
  102. data/tracks/javascript/Makefile +2 -8
  103. data/tracks/javascript/SETUP.md +1 -2
  104. data/tracks/javascript/docs/INSTALLATION.md +3 -4
  105. data/tracks/javascript/docs/TESTS.md +14 -26
  106. data/tracks/javascript/exercises/hamming/example.js +7 -11
  107. data/tracks/javascript/exercises/hello-world/HINTS.md +3 -3
  108. data/tracks/javascript/exercises/robot-simulator/example.js +72 -73
  109. data/tracks/perl6/config.json +5 -0
  110. data/tracks/perl6/exercises/clock/Clock.pm6 +4 -0
  111. data/tracks/perl6/exercises/clock/Example.pm6 +12 -0
  112. data/tracks/perl6/exercises/clock/clock.t +534 -0
  113. data/tracks/perl6/exercises/clock/example.yaml +16 -0
  114. data/tracks/perl6/exercises/robot-name/Example.pm +11 -4
  115. data/tracks/php/exercises/hello-world/hello-world.php +1 -1
  116. data/tracks/php/exercises/hello-world/hello-world_test.php +1 -11
  117. data/tracks/php/exercises/robot-name/robot-name_test.php +1 -0
  118. data/tracks/purescript/config.json +7 -0
  119. data/tracks/purescript/exercises/largest-series-product/bower.json +16 -0
  120. data/tracks/purescript/exercises/largest-series-product/examples/src/LargestSeriesProduct.purs +31 -0
  121. data/tracks/purescript/exercises/largest-series-product/src/LargestSeriesProduct.purs +3 -0
  122. data/tracks/purescript/exercises/largest-series-product/test/Main.purs +73 -0
  123. data/tracks/python/exercises/sublist/sublist_test.py +94 -55
  124. data/tracks/ruby/README.md +38 -25
  125. data/tracks/ruby/exercises/hamming/example.tt +6 -4
  126. data/tracks/ruby/exercises/hamming/hamming_test.rb +4 -5
  127. data/tracks/ruby/exercises/linked-list/linked_list_test.rb +16 -0
  128. data/tracks/ruby/exercises/luhn/luhn_test.rb +5 -5
  129. data/tracks/ruby/exercises/ocr-numbers/.meta/.version +1 -0
  130. data/tracks/ruby/exercises/ocr-numbers/example.rb +42 -61
  131. data/tracks/ruby/exercises/ocr-numbers/example.tt +21 -0
  132. data/tracks/ruby/exercises/ocr-numbers/ocr_numbers_test.rb +63 -138
  133. data/tracks/ruby/lib/generator/exercise_cases.rb +43 -0
  134. data/tracks/ruby/lib/generator/underscore.rb +9 -0
  135. data/tracks/ruby/lib/hamming_cases.rb +9 -14
  136. data/tracks/ruby/lib/luhn_cases.rb +2 -18
  137. data/tracks/ruby/lib/ocr_numbers_cases.rb +20 -0
  138. data/tracks/ruby/lib/pig_latin_cases.rb +2 -12
  139. data/tracks/ruby/test/generator/underscore_test.rb +23 -0
  140. data/tracks/scala/config.json +316 -316
  141. metadata +26 -10
  142. data/tracks/cpp/exercises/etl/require_equal_containers.h +0 -88
  143. data/tracks/cpp/exercises/grade-school/require_equal_containers.h +0 -88
  144. data/tracks/cpp/exercises/nucleotide-count/require_equal_containers.h +0 -88
  145. data/tracks/cpp/exercises/series/require_equal_containers.h +0 -88
  146. data/tracks/cpp/exercises/word-count/require_equal_containers.h +0 -88
  147. data/tracks/javascript/exercises/acronym/package.json +0 -12
  148. data/tracks/javascript/package.json +0 -12
@@ -51,6 +51,7 @@ include 'rna-transcription'
51
51
  include 'robot-name'
52
52
  include 'robot-simulator'
53
53
  include 'roman-numerals'
54
+ include 'saddle-points'
54
55
  include 'scrabble-score'
55
56
  include 'secret-handshake'
56
57
  include 'series'
@@ -5,8 +5,10 @@ sudo: false
5
5
  node_js:
6
6
  - 5.7
7
7
 
8
+ install:
9
+ - "npm install -g jasmine"
10
+
8
11
  script:
9
12
  - "make test"
10
13
  - "./bin/fetch-configlet"
11
14
  - "./bin/configlet ."
12
-
@@ -12,20 +12,14 @@ FILEEXT := "js"
12
12
  EXAMPLE := "example.$(FILEEXT)"
13
13
  TSTFILE := "$(subst _,-,$(ASSIGNMENT)).spec.$(FILEEXT)"
14
14
 
15
- # development dependencies
16
- node_modules: package.json
17
- @npm prune
18
- @npm install
19
-
20
- test-assignment: node_modules
15
+ test-assignment:
21
16
  @echo "running tests for: $(ASSIGNMENT)"
22
17
  @cp big-integer.$(FILEEXT) $(OUTDIR)
23
18
  @cp exercises/$(ASSIGNMENT)/$(TSTFILE) $(OUTDIR)
24
19
  @cp exercises/$(ASSIGNMENT)/$(EXAMPLE) $(OUTDIR)/$(subst _,-,$(ASSIGNMENT)).$(FILEEXT)
25
20
  #@sed -i.original 's/\bxit\b/it/g' $(OUTDIR)/*spec.$(FILEEXT)
26
21
  @sed 's/xit/it/g' exercises/$(ASSIGNMENT)/$(TSTFILE) > $(OUTDIR)/$(TSTFILE)
27
- @./node_modules/.bin/jasmine-node --captureExceptions $(OUTDIR)/$(TSTFILE)
22
+ @jasmine --random=true $(OUTDIR)/$(TSTFILE)
28
23
 
29
24
  test:
30
25
  @for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) -s test-assignment || exit 1; done
31
-
@@ -9,10 +9,9 @@ http://exercism.io/languages/javascript
9
9
 
10
10
  Execute the tests with:
11
11
 
12
- jasmine-node .
12
+ jasmine .
13
13
 
14
14
  In many test suites all but the first test have been skipped.
15
15
 
16
16
  Once you get a test passing, you can unskip the next one by
17
17
  changing `xit` to `it`.
18
-
@@ -15,15 +15,14 @@ If you are using a different distribution or package manager, you can find a com
15
15
 
16
16
  ## Installing additional tools
17
17
 
18
- The next step is to install `jasmine-node` globally so that you can run JavaScript tests:
18
+ The next step is to install [Jasmine](https://jasmine.github.io/) globally so that you can run JavaScript tests:
19
19
 
20
- npm install jasmine-node -g
20
+ npm install -g jasmine
21
21
 
22
22
  Depending on your setup, you may need super user privileges to install an `npm` module globally. This is the case if you've used the official installer linked to above. If `npm` gives you an error saying you don't have access, add `sudo` to the command above:
23
23
 
24
- sudo npm install jasmine-node -g
24
+ sudo npm install -g jasmine
25
25
 
26
26
  If you've used the official installer, your `PATH` should have been automatically configured, but if your shell has trouble locating your globally installed modules—or if you build Node.js from source—update your `PATH` to include the `npm` binaries by adding the following to either `~/.bash_profile` or `~/.zshrc`:
27
27
 
28
28
  export PATH=/usr/local/share/npm/bin:$PATH
29
-
@@ -1,37 +1,23 @@
1
- After configuring `exercism` command-line client you can fetch the very next exercise
1
+ With the first few exercises, you will get a skeleton file with the exported modules.
2
+ For later ones, you can find more information about modules in the [node documentation](http://nodejs.org/api/modules.html#modules_module_exports).
2
3
 
3
- exercism fetch javascript
4
-
5
- or you can fetch a specific exercise, passing the exercise name after the language. For example, to fetch the `bob` exercise:
6
-
7
- exercism fetch javascript bob
8
-
9
- Now, it's time to run some tests. Move to the folder where that exercise's files are located (a path similar to `<EXERCISM_HOME_DIR>/<TRACK_ID>/<EXERCISE>`) and run the tests with the `jasmine-node` command you should have installed on the *Installing JavaScript* step:
4
+ For running tests, install `jasmine` as described in the [Installing Javascript section](http://exercism.io/languages/javascript/installing).
5
+ Move to the folder where that exercise's files are located (a path similar to <EXERCISM_HOME_DIR>/javascript/<EXERCISE>).
10
6
 
11
7
  cd ~/exercism/javascript/bob
12
- jasmine-node bob_test.spec.js
13
-
14
- *Note that `~/exercism` is the default folder for `EXERCISM_HOME_DIR`. Be sure you use your configured folder for it*
15
-
16
- ## Making Your First Node Module
8
+ jasmine bob_test.spec.js
17
9
 
18
- To create a module that can be loaded with `var Bob = require('./bob.js');`, put this code in `bob.js`:
10
+ Only the first test will be executed, all the others have been marked pending using `xit` or `xdescribe`.
11
+ As you keep solving the exercise, one by one change all `xit` and `xdescribe` to `it` and `describe` respectively to run all the tests.
12
+ See [Test Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development) to know more about this approach.
13
+ When all tests pass, you are ready to submit!
19
14
 
20
- var Bob = function() {};
21
-
22
- Bob.prototype.hey = function(what) {
23
- //
24
- // Your solution to the exercise goes here
25
- //
26
- };
27
-
28
- module.exports = Bob;
29
-
30
- You can find more information about modules in the [node documentation](http://nodejs.org/api/modules.html#modules_module_exports). To make it easier to get started, there's a "skeleton" bob.js file in the directory
31
- for the first exercise.
32
15
 
33
16
  ## Visual Studio on Windows
34
17
 
18
+ You can use any editor of your choice to write javascript. Here are just some instructions for using and running tests in `Visual Studio`.
19
+ You are free to skip this section if you are not using `Visual Studio` on `Windows`.
20
+
35
21
  Install [Visual Studio Express 2013 for web](http://www.visualstudio.com/en-us/products/visual-studio-express-vs.aspx). This will include the IDE and web development tools.
36
22
 
37
23
  To get started, you can download a Visual Studio solution that is already set up to work with JavaScript and the other languages that Visual Studio supports.
@@ -67,6 +53,8 @@ If you do not see any output from running the tests, you are likely not in a Nod
67
53
 
68
54
  ## Setting Up a Linter
69
55
 
56
+ ** Note: This section is completely optional **
57
+
70
58
  A linter is like a tester for your code's style and formatting. In some languages there are many acceptable styles, and using a linter allows you to be internally consistent (e.g. Ruby), or adhere to one of many common styles. In other languages there are fewer choices, and a linter allows programmers to look at code from a great variety of sources and still feel at home (e.g. Go). You can read more [here](https://en.wikipedia.org/wiki/Lint_(software)).
71
59
 
72
60
  The old standard linter for JavaScript is [JSLint](http://jslint.com). However, it is controversially picky. [JSHint](http://jshint.com) is another popular linter. We suggest using [ESLint](http://eslint.org), which is more customizable than either JSLint or JSHint, and is well-run.
@@ -1,23 +1,19 @@
1
1
  function Hamming() {}
2
2
 
3
3
  Hamming.prototype.compute = function (strand1, strand2) {
4
- var len1 = strand1.length;
5
- var len2 = strand2.length;
6
-
7
- if (len1 !== len2) {
4
+ if (strand1.length !== strand2.length) {
8
5
  throw new Error('DNA strands must be of equal length.');
9
6
  }
10
7
 
11
- var out = -0;
12
- var idx = -1;
13
- var end = Math.max(len1, len2);
8
+ var distance = 0;
14
9
 
15
- while (++idx < end) {
16
- if (strand1[idx] !== strand2[idx]) out++;
10
+ for (var i = 0; i < strand1.length; i++) {
11
+ if (strand1[i] !== strand2[i]) {
12
+ distance++;
13
+ }
17
14
  }
18
15
 
19
- return out;
16
+ return distance;
20
17
  };
21
18
 
22
19
  module.exports = Hamming;
23
-
@@ -24,7 +24,7 @@ This is the first test:
24
24
 
25
25
  Run the test now, with the following command on the command-line:
26
26
 
27
- jasmine-node .
27
+ jasmine .
28
28
 
29
29
  The test fails, which makes sense since you've not written any code yet.
30
30
 
@@ -76,7 +76,7 @@ Try changing the function in hello-world.js so that it says
76
76
 
77
77
  Then run the tests again from the command-line:
78
78
 
79
- jasmine-node .
79
+ jasmine .
80
80
 
81
81
  Notice how it changes the failure message.
82
82
 
@@ -89,7 +89,7 @@ Once the test is passing, look at the second test in hello-world.spec.js. It loo
89
89
  });
90
90
 
91
91
  This test starts with `xit` instead of `it`.
92
- That means that when jasmine-node runs the tests,
92
+ That means that when Jasmine runs the tests,
93
93
  the test will be skipped.
94
94
 
95
95
  Change the test so that it starts with `it`,
@@ -1,88 +1,87 @@
1
- 'use strict';
1
+ var Robot = (function () {
2
+ 'use strict';
2
3
 
3
- var Robot = function () {
4
- this.coordinates = [0, 0];
5
- this.bearing = 'north';
6
- };
7
-
8
- Robot.prototype.at = function (xcoord, ycoord) {
9
- this.coordinates = [xcoord, ycoord];
10
- };
11
-
12
- Robot.prototype.orient = function (direction) {
13
- if (direction != 'north' &&
14
- direction != 'south' &&
15
- direction != 'east' &&
16
- direction != 'west') {
17
- throw 'Invalid Robot Bearing'
4
+ var VALID_DIRECTIONS = ['north', 'east', 'south', 'west']
5
+ var INSTRUCTION_KEYS = {
6
+ A: 'advance',
7
+ L: 'turnLeft',
8
+ R: 'turnRight'
18
9
  }
19
10
 
20
- this.bearing = direction;
21
- return 'The robot is pointed ' + direction;
22
- };
11
+ function Robot () {
12
+ this.coordinates = [0, 0];
13
+ this.bearing = 'north';
14
+ };
23
15
 
24
- Robot.prototype.advance = function () {
16
+ Robot.prototype.at = function (x, y) {
17
+ this.coordinates = [x, y];
18
+ };
25
19
 
26
- if (this.bearing === 'north') {
27
- this.coordinates[1] += 1;
28
- } else if (this.bearing === 'south') {
29
- this.coordinates[1] -= 1;
30
- } else if (this.bearing === 'east') {
31
- this.coordinates[0] += 1;
32
- } else if (this.bearing === 'west') {
33
- this.coordinates[0] -= 1;
34
- }
35
- };
20
+ Robot.prototype.orient = function (direction) {
21
+ if (VALID_DIRECTIONS.indexOf(direction) === -1) {
22
+ throw new Error('Invalid Robot Bearing');
23
+ }
36
24
 
37
- Robot.prototype.turnLeft = function () {
25
+ this.bearing = direction;
26
+ };
38
27
 
39
- if (this.bearing === 'north') {
40
- this.orient('west');
41
- } else if (this.bearing === 'south') {
42
- this.orient('east');
43
- } else if (this.bearing === 'east') {
44
- this.orient('north');
45
- } else if (this.bearing === 'west') {
46
- this.orient('south');
47
- }
48
- };
28
+ Robot.prototype.advance = function () {
29
+ switch (this.bearing) {
30
+ case 'north':
31
+ this.coordinates[1]++;
32
+ break;
33
+ case 'east':
34
+ this.coordinates[0]++;
35
+ break;
36
+ case 'south':
37
+ this.coordinates[1]--;
38
+ break;
39
+ case 'west':
40
+ this.coordinates[0]--;
41
+ break;
42
+ };
43
+ };
49
44
 
50
- Robot.prototype.turnRight = function () {
45
+ Robot.prototype.turnLeft = function () {
46
+ var directionPosition = VALID_DIRECTIONS.indexOf(this.bearing);
51
47
 
52
- if (this.bearing === 'north') {
53
- this.orient('east');
54
- } else if (this.bearing === 'south') {
55
- this.orient('west');
56
- } else if (this.bearing === 'east') {
57
- this.orient('south');
58
- } else if (this.bearing === 'west') {
59
- this.orient('north');
60
- }
61
- };
48
+ if (directionPosition > 0) {
49
+ this.orient(VALID_DIRECTIONS[--directionPosition]);
50
+ } else {
51
+ this.orient(VALID_DIRECTIONS[VALID_DIRECTIONS.length - 1]);
52
+ }
53
+ };
54
+
55
+ Robot.prototype.turnRight = function () {
56
+ var directionPosition = VALID_DIRECTIONS.indexOf(this.bearing);
62
57
 
63
- Robot.prototype.instructions = function (s) {
64
- var result = [];
65
- s.split('').forEach(function (character) {
66
- if (character === 'L') {
67
- result.push('turnLeft');
68
- } else if (character === 'R') {
69
- result.push('turnRight');
70
- } else if (character === 'A') {
71
- result.push('advance');
58
+ if (directionPosition < (VALID_DIRECTIONS.length - 1)) {
59
+ this.orient(VALID_DIRECTIONS[++directionPosition]);
60
+ } else {
61
+ this.orient(VALID_DIRECTIONS[0]);
72
62
  }
73
- });
74
- return result;
75
- };
63
+ };
64
+
65
+ Robot.prototype.instructions = function (instructionKeys) {
66
+ return instructionKeys.split('')
67
+ .map(function (key) {
68
+ return INSTRUCTION_KEYS[key];
69
+ });
70
+ };
71
+
72
+ Robot.prototype.place = function (args) {
73
+ this.coordinates = [args.x, args.y];
74
+ this.bearing = args.direction;
75
+ };
76
76
 
77
- Robot.prototype.place = function (args) {
78
- this.coordinates = [args.x, args.y];
79
- this.bearing = args.direction;
80
- };
77
+ Robot.prototype.evaluate = function (instructionKeys) {
78
+ this.instructions(instructionKeys)
79
+ .forEach(function (instruction) {
80
+ this[instruction]();
81
+ }, this);
82
+ };
81
83
 
82
- Robot.prototype.evaluate = function (s) {
83
- this.instructions(s).forEach(function (instruction) {
84
- this[instruction]();
85
- }, this);
86
- };
84
+ return Robot
85
+ })()
87
86
 
88
87
  module.exports = Robot;
@@ -49,6 +49,11 @@
49
49
  "slug": "raindrops",
50
50
  "topics": []
51
51
  },
52
+ {
53
+ "difficulty": 1,
54
+ "slug": "clock",
55
+ "topics": []
56
+ },
52
57
  {
53
58
  "difficulty": 1,
54
59
  "slug": "scrabble-score",
@@ -0,0 +1,4 @@
1
+ unit class Clock:ver<1>;
2
+
3
+ has $.hour;
4
+ has $.minute;
@@ -0,0 +1,12 @@
1
+ unit class Clock:ver<1>;
2
+
3
+ has Int:D $.hour = 0;
4
+ has Int:D $.minute = 0;
5
+
6
+ method time is export {
7
+ sprintf '%02d:%02d', ($!hour + $!minute div 60) % 24, $!minute % 60;
8
+ }
9
+
10
+ method add-minutes (Int:D $min) is export {
11
+ $!minute += $min and return self;
12
+ }
@@ -0,0 +1,534 @@
1
+ #!/usr/bin/env perl6
2
+ use v6;
3
+ use Test;
4
+ use lib my $dir = $?FILE.IO.dirname;
5
+ use JSON::Tiny;
6
+
7
+ my $exercise = 'Clock';
8
+ my $version = v1;
9
+ my $module = %*ENV<EXERCISM> ?? 'Example' !! $exercise;
10
+ plan 54;
11
+
12
+ use-ok $module or bail-out;
13
+ require ::($module);
14
+
15
+ if ::($exercise).^ver !~~ $version {
16
+ warn "\nExercise version mismatch. Further tests may fail!"
17
+ ~ "\n$exercise is $(::($exercise).^ver.gist). "
18
+ ~ "Test is $($version.gist).\n";
19
+ bail-out 'Example version must match test version.' if %*ENV<EXERCISM>;
20
+ }
21
+
22
+ subtest 'Class methods', {
23
+ ok ::($exercise).can($_), $_ for <time add-minutes>;
24
+ }
25
+
26
+ my $c-data;
27
+ is ::($exercise).new(hour => .<hour>, minute => .<minute>).?time, |.<expected description> for @($c-data<cases>[0]<cases>);
28
+ for @($c-data<cases>[1]<cases>) {
29
+ my $clock = ::($exercise).new(hour => .<hour>, minute => .<minute>);
30
+ $clock.?add-minutes(.<add>);
31
+ is $clock.?time, |.<expected description>;
32
+ }
33
+ is ::($exercise).new(hour => .<clock1><hour>, minute => .<clock1><minute>).?time eq
34
+ ::($exercise).new(hour => .<clock2><hour>, minute => .<clock2><minute>).?time,
35
+ |.<expected description> for @($c-data<cases>[2]<cases>);
36
+ todo 'optional test' unless %*ENV<EXERCISM>;
37
+ is ::($exercise).new(:0hour,:0minute).?add-minutes(65).?time, '01:05', 'add-minutes method can be chained';
38
+
39
+ if %*ENV<EXERCISM> && (my $c-data-file =
40
+ "$dir/../../x-common/exercises/{$dir.IO.resolve.basename}/canonical-data.json".IO.resolve) ~~ :f
41
+ { is-deeply $c-data, from-json($c-data-file.slurp), 'canonical-data' } else { skip }
42
+
43
+ done-testing;
44
+
45
+ INIT {
46
+ $c-data := from-json q:to/END/;
47
+
48
+ {
49
+ "exercise": "clock",
50
+ "version": "1.0.0",
51
+ "comments": [
52
+ "Most languages require constructing a clock with initial values,",
53
+ "adding a positive or negative number of minutes, and testing equality",
54
+ "in some language-native way. Some languages require separate add and",
55
+ "subtract functions. Negative and out of range values are generally",
56
+ "expected to wrap around rather than represent errors."
57
+ ],
58
+ "cases": [
59
+ {
60
+ "description": "Test creating a new clock with an initial time.",
61
+ "cases": [
62
+ {
63
+ "description": "on the hour",
64
+ "property": "create",
65
+ "hour": 8,
66
+ "minute": 0,
67
+ "expected": "08:00"
68
+ },
69
+ {
70
+ "description": "past the hour",
71
+ "property": "create",
72
+ "hour": 11,
73
+ "minute": 9,
74
+ "expected": "11:09"
75
+ },
76
+ {
77
+ "description": "midnight is zero hours",
78
+ "property": "create",
79
+ "hour": 24,
80
+ "minute": 0,
81
+ "expected": "00:00"
82
+ },
83
+ {
84
+ "description": "hour rolls over",
85
+ "property": "create",
86
+ "hour": 25,
87
+ "minute": 0,
88
+ "expected": "01:00"
89
+ },
90
+ {
91
+ "description": "hour rolls over continuously",
92
+ "property": "create",
93
+ "hour": 100,
94
+ "minute": 0,
95
+ "expected": "04:00"
96
+ },
97
+ {
98
+ "description": "sixty minutes is next hour",
99
+ "property": "create",
100
+ "hour": 1,
101
+ "minute": 60,
102
+ "expected": "02:00"
103
+ },
104
+ {
105
+ "description": "minutes roll over",
106
+ "property": "create",
107
+ "hour": 0,
108
+ "minute": 160,
109
+ "expected": "02:40"
110
+ },
111
+ {
112
+ "description": "minutes roll over continuously",
113
+ "property": "create",
114
+ "hour": 0,
115
+ "minute": 1723,
116
+ "expected": "04:43"
117
+ },
118
+ {
119
+ "description": "hour and minutes roll over",
120
+ "property": "create",
121
+ "hour": 25,
122
+ "minute": 160,
123
+ "expected": "03:40"
124
+ },
125
+ {
126
+ "description": "hour and minutes roll over continuously",
127
+ "property": "create",
128
+ "hour": 201,
129
+ "minute": 3001,
130
+ "expected": "11:01"
131
+ },
132
+ {
133
+ "description": "hour and minutes roll over to exactly midnight",
134
+ "property": "create",
135
+ "hour": 72,
136
+ "minute": 8640,
137
+ "expected": "00:00"
138
+ },
139
+ {
140
+ "description": "negative hour",
141
+ "property": "create",
142
+ "hour": -1,
143
+ "minute": 15,
144
+ "expected": "23:15"
145
+ },
146
+ {
147
+ "description": "negative hour rolls over",
148
+ "property": "create",
149
+ "hour": -25,
150
+ "minute": 0,
151
+ "expected": "23:00"
152
+ },
153
+ {
154
+ "description": "negative hour rolls over continuously",
155
+ "property": "create",
156
+ "hour": -91,
157
+ "minute": 0,
158
+ "expected": "05:00"
159
+ },
160
+ {
161
+ "description": "negative minutes",
162
+ "property": "create",
163
+ "hour": 1,
164
+ "minute": -40,
165
+ "expected": "00:20"
166
+ },
167
+ {
168
+ "description": "negative minutes roll over",
169
+ "property": "create",
170
+ "hour": 1,
171
+ "minute": -160,
172
+ "expected": "22:20"
173
+ },
174
+ {
175
+ "description": "negative minutes roll over continuously",
176
+ "property": "create",
177
+ "hour": 1,
178
+ "minute": -4820,
179
+ "expected": "16:40"
180
+ },
181
+ {
182
+ "description": "negative hour and minutes both roll over",
183
+ "property": "create",
184
+ "hour": -25,
185
+ "minute": -160,
186
+ "expected": "20:20"
187
+ },
188
+ {
189
+ "description": "negative hour and minutes both roll over continuously",
190
+ "property": "create",
191
+ "hour": -121,
192
+ "minute": -5810,
193
+ "expected": "22:10"
194
+ }
195
+ ]
196
+ },
197
+ {
198
+ "description": "Test adding and subtracting minutes.",
199
+ "cases": [
200
+ {
201
+ "description": "add minutes",
202
+ "property": "add",
203
+ "hour": 10,
204
+ "minute": 0,
205
+ "add": 3,
206
+ "expected": "10:03"
207
+ },
208
+ {
209
+ "description": "add no minutes",
210
+ "property": "add",
211
+ "hour": 6,
212
+ "minute": 41,
213
+ "add": 0,
214
+ "expected": "06:41"
215
+ },
216
+ {
217
+ "description": "add to next hour",
218
+ "property": "add",
219
+ "hour": 0,
220
+ "minute": 45,
221
+ "add": 40,
222
+ "expected": "01:25"
223
+ },
224
+ {
225
+ "description": "add more than one hour",
226
+ "property": "add",
227
+ "hour": 10,
228
+ "minute": 0,
229
+ "add": 61,
230
+ "expected": "11:01"
231
+ },
232
+ {
233
+ "description": "add more than two hours with carry",
234
+ "property": "add",
235
+ "hour": 0,
236
+ "minute": 45,
237
+ "add": 160,
238
+ "expected": "03:25"
239
+ },
240
+ {
241
+ "description": "add across midnight",
242
+ "property": "add",
243
+ "hour": 23,
244
+ "minute": 59,
245
+ "add": 2,
246
+ "expected": "00:01"
247
+ },
248
+ {
249
+ "description": "add more than one day (1500 min = 25 hrs)",
250
+ "property": "add",
251
+ "hour": 5,
252
+ "minute": 32,
253
+ "add": 1500,
254
+ "expected": "06:32"
255
+ },
256
+ {
257
+ "description": "add more than two days",
258
+ "property": "add",
259
+ "hour": 1,
260
+ "minute": 1,
261
+ "add": 3500,
262
+ "expected": "11:21"
263
+ },
264
+ {
265
+ "description": "subtract minutes",
266
+ "property": "add",
267
+ "hour": 10,
268
+ "minute": 3,
269
+ "add": -3,
270
+ "expected": "10:00"
271
+ },
272
+ {
273
+ "description": "subtract to previous hour",
274
+ "property": "add",
275
+ "hour": 10,
276
+ "minute": 3,
277
+ "add": -30,
278
+ "expected": "09:33"
279
+ },
280
+ {
281
+ "description": "subtract more than an hour",
282
+ "property": "add",
283
+ "hour": 10,
284
+ "minute": 3,
285
+ "add": -70,
286
+ "expected": "08:53"
287
+ },
288
+ {
289
+ "description": "subtract across midnight",
290
+ "property": "add",
291
+ "hour": 0,
292
+ "minute": 3,
293
+ "add": -4,
294
+ "expected": "23:59"
295
+ },
296
+ {
297
+ "description": "subtract more than two hours",
298
+ "property": "add",
299
+ "hour": 0,
300
+ "minute": 0,
301
+ "add": -160,
302
+ "expected": "21:20"
303
+ },
304
+ {
305
+ "description": "subtract more than two hours with borrow",
306
+ "property": "add",
307
+ "hour": 6,
308
+ "minute": 15,
309
+ "add": -160,
310
+ "expected": "03:35"
311
+ },
312
+ {
313
+ "description": "subtract more than one day (1500 min = 25 hrs)",
314
+ "property": "add",
315
+ "hour": 5,
316
+ "minute": 32,
317
+ "add": -1500,
318
+ "expected": "04:32"
319
+ },
320
+ {
321
+ "description": "subtract more than two days",
322
+ "property": "add",
323
+ "hour": 2,
324
+ "minute": 20,
325
+ "add": -3000,
326
+ "expected": "00:20"
327
+ }
328
+ ]
329
+ },
330
+ {
331
+ "description": "Construct two separate clocks, set times, test if they are equal.",
332
+ "cases": [
333
+ {
334
+ "description": "clocks with same time",
335
+ "property": "equal",
336
+ "clock1": {
337
+ "hour": 15,
338
+ "minute": 37
339
+ },
340
+ "clock2": {
341
+ "hour": 15,
342
+ "minute": 37
343
+ },
344
+ "expected": true
345
+ },
346
+ {
347
+ "description": "clocks a minute apart",
348
+ "property": "equal",
349
+ "clock1": {
350
+ "hour": 15,
351
+ "minute": 36
352
+ },
353
+ "clock2": {
354
+ "hour": 15,
355
+ "minute": 37
356
+ },
357
+ "expected": false
358
+ },
359
+ {
360
+ "description": "clocks an hour apart",
361
+ "property": "equal",
362
+ "clock1": {
363
+ "hour": 14,
364
+ "minute": 37
365
+ },
366
+ "clock2": {
367
+ "hour": 15,
368
+ "minute": 37
369
+ },
370
+ "expected": false
371
+ },
372
+ {
373
+ "description": "clocks with hour overflow",
374
+ "property": "equal",
375
+ "clock1": {
376
+ "hour": 10,
377
+ "minute": 37
378
+ },
379
+ "clock2": {
380
+ "hour": 34,
381
+ "minute": 37
382
+ },
383
+ "expected": true
384
+ },
385
+ {
386
+ "description": "clocks with hour overflow by several days",
387
+ "property": "equal",
388
+ "clock1": {
389
+ "hour": 3,
390
+ "minute": 11
391
+ },
392
+ "clock2": {
393
+ "hour": 99,
394
+ "minute": 11
395
+ },
396
+ "expected": true
397
+ },
398
+ {
399
+ "description": "clocks with negative hour",
400
+ "property": "equal",
401
+ "clock1": {
402
+ "hour": 22,
403
+ "minute": 40
404
+ },
405
+ "clock2": {
406
+ "hour": -2,
407
+ "minute": 40
408
+ },
409
+ "expected": true
410
+ },
411
+ {
412
+ "description": "clocks with negative hour that wraps",
413
+ "property": "equal",
414
+ "clock1": {
415
+ "hour": 17,
416
+ "minute": 3
417
+ },
418
+ "clock2": {
419
+ "hour": -31,
420
+ "minute": 3
421
+ },
422
+ "expected": true
423
+ },
424
+ {
425
+ "description": "clocks with negative hour that wraps multiple times",
426
+ "property": "equal",
427
+ "clock1": {
428
+ "hour": 13,
429
+ "minute": 49
430
+ },
431
+ "clock2": {
432
+ "hour": -83,
433
+ "minute": 49
434
+ },
435
+ "expected": true
436
+ },
437
+ {
438
+ "description": "clocks with minute overflow",
439
+ "property": "equal",
440
+ "clock1": {
441
+ "hour": 0,
442
+ "minute": 1
443
+ },
444
+ "clock2": {
445
+ "hour": 0,
446
+ "minute": 1441
447
+ },
448
+ "expected": true
449
+ },
450
+ {
451
+ "description": "clocks with minute overflow by several days",
452
+ "property": "equal",
453
+ "clock1": {
454
+ "hour": 2,
455
+ "minute": 2
456
+ },
457
+ "clock2": {
458
+ "hour": 2,
459
+ "minute": 4322
460
+ },
461
+ "expected": true
462
+ },
463
+ {
464
+ "description": "clocks with negative minute",
465
+ "property": "equal",
466
+ "clock1": {
467
+ "hour": 2,
468
+ "minute": 40
469
+ },
470
+ "clock2": {
471
+ "hour": 3,
472
+ "minute": -20
473
+ },
474
+ "expected": true
475
+ },
476
+ {
477
+ "description": "clocks with negative minute that wraps",
478
+ "property": "equal",
479
+ "clock1": {
480
+ "hour": 4,
481
+ "minute": 10
482
+ },
483
+ "clock2": {
484
+ "hour": 5,
485
+ "minute": -1490
486
+ },
487
+ "expected": true
488
+ },
489
+ {
490
+ "description": "clocks with negative minute that wraps multiple times",
491
+ "property": "equal",
492
+ "clock1": {
493
+ "hour": 6,
494
+ "minute": 15
495
+ },
496
+ "clock2": {
497
+ "hour": 6,
498
+ "minute": -4305
499
+ },
500
+ "expected": true
501
+ },
502
+ {
503
+ "description": "clocks with negative hours and minutes",
504
+ "property": "equal",
505
+ "clock1": {
506
+ "hour": 7,
507
+ "minute": 32
508
+ },
509
+ "clock2": {
510
+ "hour": -12,
511
+ "minute": -268
512
+ },
513
+ "expected": true
514
+ },
515
+ {
516
+ "description": "clocks with negative hours and minutes that wrap",
517
+ "property": "equal",
518
+ "clock1": {
519
+ "hour": 18,
520
+ "minute": 7
521
+ },
522
+ "clock2": {
523
+ "hour": -54,
524
+ "minute": -11513
525
+ },
526
+ "expected": true
527
+ }
528
+ ]
529
+ }
530
+ ]
531
+ }
532
+
533
+ END
534
+ }