trackler 2.2.1.176 → 2.2.1.177
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/isbn-verifier/canonical-data.json +9 -9
- data/tracks/bash/docs/LEARNING.md +1 -1
- data/tracks/bash/docs/RESOURCES.md +7 -3
- data/tracks/clojure/docs/RESOURCES.md +1 -1
- data/tracks/crystal/config.json +1 -0
- data/tracks/crystal/docs/ABOUT.md +3 -1
- data/tracks/crystal/exercises/gigasecond/spec/gigasecond_spec.cr +10 -10
- data/tracks/delphi/exercises/isbn-verifier/uTestISBNVerifier.pas +7 -7
- data/tracks/erlang/config.json +36 -0
- data/tracks/erlang/exercises/armstrong-numbers/test/armstrong_numbers_tests.erl +1 -1
- data/tracks/erlang/exercises/minesweeper/README.md +68 -0
- data/tracks/erlang/exercises/minesweeper/rebar.config +30 -0
- data/tracks/erlang/exercises/minesweeper/src/example.erl +76 -0
- data/tracks/erlang/exercises/minesweeper/src/minesweeper.app.src +9 -0
- data/tracks/erlang/exercises/minesweeper/src/minesweeper.erl +8 -0
- data/tracks/erlang/exercises/minesweeper/test/minesweeper_tests.erl +154 -0
- data/tracks/erlang/exercises/perfect-numbers/README.md +59 -0
- data/tracks/erlang/exercises/perfect-numbers/rebar.config +30 -0
- data/tracks/erlang/exercises/perfect-numbers/src/example.erl +35 -0
- data/tracks/erlang/exercises/perfect-numbers/src/perfect_numbers.app.src +9 -0
- data/tracks/erlang/exercises/perfect-numbers/src/perfect_numbers.erl +8 -0
- data/tracks/erlang/exercises/perfect-numbers/test/perfect_numbers_tests.erl +48 -0
- data/tracks/erlang/exercises/secret-handshake/README.md +70 -0
- data/tracks/erlang/exercises/secret-handshake/rebar.config +30 -0
- data/tracks/erlang/exercises/secret-handshake/src/example.erl +19 -0
- data/tracks/erlang/exercises/secret-handshake/src/secret_handshake.app.src +9 -0
- data/tracks/erlang/exercises/secret-handshake/src/secret_handshake.erl +8 -0
- data/tracks/erlang/exercises/secret-handshake/test/secret_handshake_tests.erl +45 -0
- data/tracks/go/.travis.yml +2 -2
- data/tracks/nim/config.json +2 -2
- data/tracks/nim/docs/SNIPPET.txt +4 -1
- data/tracks/python/config.json +12 -0
- data/tracks/python/exercises/ledger/README.md +60 -0
- data/tracks/python/exercises/ledger/example.py +85 -0
- data/tracks/python/exercises/ledger/ledger.py +298 -0
- data/tracks/python/exercises/ledger/ledger_test.py +147 -0
- data/tracks/python/exercises/linked-list/example.py +8 -8
- data/tracks/python/exercises/linked-list/linked_list.py +1 -1
- data/tracks/python/exercises/reverse-string/example.py +2 -2
- data/tracks/python/exercises/reverse-string/reverse_string.py +1 -1
- data/tracks/reasonml/config.json +24 -0
- data/tracks/reasonml/exercises/armstrong-numbers/README.md +35 -0
- data/tracks/reasonml/exercises/armstrong-numbers/__tests__/ArmstrongNumbers_test.re +37 -0
- data/tracks/reasonml/exercises/armstrong-numbers/bsconfig.json +25 -0
- data/tracks/reasonml/exercises/armstrong-numbers/package-lock.json +5835 -0
- data/tracks/reasonml/exercises/armstrong-numbers/package.json +20 -0
- data/tracks/reasonml/exercises/armstrong-numbers/src/ArmstrongNumbers.rei +1 -0
- data/tracks/reasonml/exercises/armstrong-numbers/src/Example.re +17 -0
- data/tracks/reasonml/exercises/isogram/README.md +38 -0
- data/tracks/reasonml/exercises/isogram/__tests__/Isogram_test.re +41 -0
- data/tracks/reasonml/exercises/isogram/bsconfig.json +25 -0
- data/tracks/reasonml/exercises/isogram/package-lock.json +5835 -0
- data/tracks/reasonml/exercises/isogram/package.json +20 -0
- data/tracks/reasonml/exercises/isogram/src/Example.re +17 -0
- data/tracks/reasonml/exercises/isogram/src/Isogram.rei +1 -0
- data/tracks/rust/config.json +95 -94
- data/tracks/rust/exercises/diffie-hellman/.meta/hints.md +2 -0
- data/tracks/rust/exercises/diffie-hellman/README.md +4 -0
- data/tracks/rust/exercises/diffie-hellman/example.rs +24 -2
- data/tracks/rust/exercises/diffie-hellman/tests/diffie-hellman.rs +30 -0
- data/tracks/rust/exercises/{twofer → two-fer}/.gitignore +0 -0
- data/tracks/rust/exercises/{twofer → two-fer}/Cargo.toml +0 -0
- data/tracks/rust/exercises/{twofer → two-fer}/README.md +1 -1
- data/tracks/rust/exercises/{twofer → two-fer}/example.rs +0 -0
- data/tracks/rust/exercises/{twofer → two-fer}/src/lib.rs +0 -0
- data/tracks/rust/exercises/{twofer → two-fer}/tests/two-fer.rs +0 -0
- metadata +45 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2e5bcb62b38646413cb1b774d068463bb8f4a70c
|
|
4
|
+
data.tar.gz: 955ab5796404df47072cdb28d09600e3edbff1bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd13a222bd29b3d53520d44f84b0cee0fad4dedf5b27de00143c1738689a5de48b74c1f17ceb92bcbb2f260d494b9b1f973b6d03574659c2cbac50a9e0a61f89
|
|
7
|
+
data.tar.gz: 1f33b0a29f2a0800d0ef2151dd0f9a82b0659e504a2557d594b6d168f7d9587a4dd64d43764dea2f4bb2b13adfd6dc858088e116008f14377e404627e64c1a8f
|
data/lib/trackler/version.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"exercise": "isbn-verifier",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"comments": [
|
|
5
5
|
"An expected value of true indicates a valid ISBN-10, ",
|
|
6
6
|
"whereas false means the ISBN-10 is invalid."
|
|
@@ -102,14 +102,6 @@
|
|
|
102
102
|
},
|
|
103
103
|
"expected": false
|
|
104
104
|
},
|
|
105
|
-
{
|
|
106
|
-
"description": "too long isbn",
|
|
107
|
-
"property": "isValid",
|
|
108
|
-
"input": {
|
|
109
|
-
"isbn": "3-598-21507-XX"
|
|
110
|
-
},
|
|
111
|
-
"expected": false
|
|
112
|
-
},
|
|
113
105
|
{
|
|
114
106
|
"description": "check digit of X should not be used for 0",
|
|
115
107
|
"property": "isValid",
|
|
@@ -141,6 +133,14 @@
|
|
|
141
133
|
"isbn": "3132P34035"
|
|
142
134
|
},
|
|
143
135
|
"expected": false
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"description": "input is too long but contains a valid isbn",
|
|
139
|
+
"property": "isValid",
|
|
140
|
+
"input": {
|
|
141
|
+
"isbn": "98245726788"
|
|
142
|
+
},
|
|
143
|
+
"expected": false
|
|
144
144
|
}
|
|
145
145
|
]
|
|
146
146
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Bash is a very powerful Unix shell and command scripting language. The man page for Bash is a well written and informational document. Additional guides, information, and examples can be found at the
|
|
1
|
+
Bash is a very powerful Unix shell and command scripting language. The man page for Bash is a well written and informational document. Additional guides, information, and examples can be found at [Greg's Wiki](http://mywiki.wooledge.org/BashGuide) and the [GNU Bash Manual](http://gnu.org/s/bash/manual). Shellcheck.net provides a web interface (and binary for some distros) that checks shell scripts for errors or common issues and provides information on how to best correct them.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
-
|
|
2
|
-
- [
|
|
3
|
-
- [
|
|
1
|
+
- Bash man page: to view it, type `man bash` in a terminal.
|
|
2
|
+
- [Bash Guide](http://mywiki.wooledge.org/BashGuide)
|
|
3
|
+
- [Bash FAQ](http://mywiki.wooledge.org/BashFAQ)
|
|
4
|
+
- [Bash Pitfalls](https://mywiki.wooledge.org/BashPitfalls)
|
|
5
|
+
- [GNU Bash Manual](http://gnu.org/s/bash/manual)
|
|
6
|
+
- [Bash-Hackers Wiki](http://wiki.bash-hackers.org/)
|
|
7
|
+
- [Shellcheck provides shell script guidelines and help](http://www.shellcheck.net/)
|
data/tracks/crystal/config.json
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
Crystal is a compiled language that is currently in the alpha stages of development.
|
|
1
|
+
Crystal is a compiled language that is currently in the alpha stages of development.
|
|
2
|
+
These are some of the language's goals:
|
|
3
|
+
|
|
2
4
|
* Ruby-inspired syntax.
|
|
3
5
|
|
|
4
6
|
* Statically type-checked but without having to specify the type of variables or method arguments.
|
|
@@ -4,28 +4,28 @@ require "../src/*"
|
|
|
4
4
|
describe "Gigasecond" do
|
|
5
5
|
describe "#from" do
|
|
6
6
|
it "finds gigsecond from 2011_04_25" do
|
|
7
|
-
result = Gigasecond.from(Time.
|
|
8
|
-
result.should eq Time.
|
|
7
|
+
result = Gigasecond.from(Time.utc(2011, 4, 25, 0, 0, 0))
|
|
8
|
+
result.should eq Time.utc(2043, 1, 1, 1, 46, 40)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
pending "finds gigsecond from 1977_06_13" do
|
|
12
|
-
result = Gigasecond.from(Time.
|
|
13
|
-
result.should eq Time.
|
|
12
|
+
result = Gigasecond.from(Time.utc(1977, 6, 13, 0, 0, 0))
|
|
13
|
+
result.should eq Time.utc(2009, 2, 19, 1, 46, 40)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
pending "finds gigsecond from 1959_07_19" do
|
|
17
|
-
result = Gigasecond.from(Time.
|
|
18
|
-
result.should eq Time.
|
|
17
|
+
result = Gigasecond.from(Time.utc(1959, 7, 19, 0, 0, 0))
|
|
18
|
+
result.should eq Time.utc(1991, 3, 27, 1, 46, 40)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
pending "finds gigsecond with full_time specified" do
|
|
22
|
-
result = Gigasecond.from(Time.
|
|
23
|
-
result.should eq Time.
|
|
22
|
+
result = Gigasecond.from(Time.utc(2015, 1, 24, 22, 0, 0))
|
|
23
|
+
result.should eq Time.utc(2046, 10, 2, 23, 46, 40)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
pending "finds gigsecond with full_time with day rollover" do
|
|
27
|
-
result = Gigasecond.from(Time.
|
|
28
|
-
result.should eq Time.
|
|
27
|
+
result = Gigasecond.from(Time.utc(2015, 1, 24, 23, 59, 59))
|
|
28
|
+
result.should eq Time.utc(2046, 10, 3, 1, 46, 39)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
pending "test_with_your_birthday" do
|
|
@@ -5,7 +5,7 @@ uses
|
|
|
5
5
|
DUnitX.TestFramework;
|
|
6
6
|
|
|
7
7
|
const
|
|
8
|
-
CanonicalVersion = '2.
|
|
8
|
+
CanonicalVersion = '2.7.0';
|
|
9
9
|
|
|
10
10
|
type
|
|
11
11
|
[TestFixture]
|
|
@@ -59,10 +59,6 @@ type
|
|
|
59
59
|
[Ignore]
|
|
60
60
|
procedure isbn_without_check_digit;
|
|
61
61
|
|
|
62
|
-
[Test]
|
|
63
|
-
[Ignore]
|
|
64
|
-
procedure too_long_isbn;
|
|
65
|
-
|
|
66
62
|
[Test]
|
|
67
63
|
[Ignore]
|
|
68
64
|
procedure check_digit_of_X_should_not_be_used_for_0;
|
|
@@ -78,6 +74,10 @@ type
|
|
|
78
74
|
[Test]
|
|
79
75
|
[Ignore]
|
|
80
76
|
procedure invalid_characters_are_not_ignored;
|
|
77
|
+
|
|
78
|
+
[Test]
|
|
79
|
+
[Ignore]
|
|
80
|
+
procedure input_is_too_long_but_contains_a_valid_isbn;
|
|
81
81
|
end;
|
|
82
82
|
|
|
83
83
|
implementation
|
|
@@ -135,9 +135,9 @@ begin
|
|
|
135
135
|
Assert.IsTrue(TIsbn.isValid('359821507X'));
|
|
136
136
|
end;
|
|
137
137
|
|
|
138
|
-
procedure ISBNVerifierTest.
|
|
138
|
+
procedure ISBNVerifierTest.input_is_too_long_but_contains_a_valid_isbn;
|
|
139
139
|
begin
|
|
140
|
-
Assert.IsFalse(TIsbn.isValid('
|
|
140
|
+
Assert.IsFalse(TIsbn.isValid('98245726788'));
|
|
141
141
|
end;
|
|
142
142
|
|
|
143
143
|
procedure ISBNVerifierTest.too_long_isbn_and_no_dashes;
|
data/tracks/erlang/config.json
CHANGED
|
@@ -119,6 +119,18 @@
|
|
|
119
119
|
"time"
|
|
120
120
|
]
|
|
121
121
|
},
|
|
122
|
+
{
|
|
123
|
+
"slug": "secret-handshake",
|
|
124
|
+
"uuid": "580309f9-65f1-480b-bdb6-c14846963c33",
|
|
125
|
+
"core": false,
|
|
126
|
+
"unlocked_by": "raindrops",
|
|
127
|
+
"difficulty": 1,
|
|
128
|
+
"topics": [
|
|
129
|
+
"control_flow_conditionals",
|
|
130
|
+
"pattern_matching",
|
|
131
|
+
"strings"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
122
134
|
{
|
|
123
135
|
"slug": "grains",
|
|
124
136
|
"uuid": "c3070adc-d434-4989-8d6b-d9e483e32d1c",
|
|
@@ -199,6 +211,17 @@
|
|
|
199
211
|
"mathematics"
|
|
200
212
|
]
|
|
201
213
|
},
|
|
214
|
+
{
|
|
215
|
+
"slug": "perfect-numbers",
|
|
216
|
+
"uuid": "8c58533a-7a1f-11e8-adc0-fa7ae01bbebc",
|
|
217
|
+
"core": false,
|
|
218
|
+
"unlocked_by": "collatz-conjecture",
|
|
219
|
+
"difficulty": 2,
|
|
220
|
+
"topics": [
|
|
221
|
+
"integers",
|
|
222
|
+
"mathematics"
|
|
223
|
+
]
|
|
224
|
+
},
|
|
202
225
|
{
|
|
203
226
|
"slug": "armstrong-numbers",
|
|
204
227
|
"uuid": "a639ce2f-48e3-46cd-9d11-955ba2a9eaaa",
|
|
@@ -517,6 +540,19 @@
|
|
|
517
540
|
"types"
|
|
518
541
|
]
|
|
519
542
|
},
|
|
543
|
+
{
|
|
544
|
+
"slug": "minesweeper",
|
|
545
|
+
"uuid": "2cf5d5ba-9820-4918-ac91-811b2a434655",
|
|
546
|
+
"core": false,
|
|
547
|
+
"unlocked_by": "accumulate",
|
|
548
|
+
"difficulty": 7,
|
|
549
|
+
"topics": [
|
|
550
|
+
"lists",
|
|
551
|
+
"parsing",
|
|
552
|
+
"strings",
|
|
553
|
+
"transforming"
|
|
554
|
+
]
|
|
555
|
+
},
|
|
520
556
|
{
|
|
521
557
|
"slug": "beer-song",
|
|
522
558
|
"uuid": "2fedc6bf-6006-4c2d-bba7-9c66265b6f62",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
-module(armstrong_numbers_tests).
|
|
5
5
|
|
|
6
|
-
-define(TESTED_MODULE, (sut(
|
|
6
|
+
-define(TESTED_MODULE, (sut(armstrong_numbers))).
|
|
7
7
|
-define(TEST_VERSION, 1).
|
|
8
8
|
-include_lib("erl_exercism/include/exercism.hrl").
|
|
9
9
|
-include_lib("eunit/include/eunit.hrl").
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Add the numbers to a minesweeper board.
|
|
2
|
+
|
|
3
|
+
Minesweeper is a popular game where the user has to find the mines using
|
|
4
|
+
numeric hints that indicate how many mines are directly adjacent
|
|
5
|
+
(horizontally, vertically, diagonally) to a square.
|
|
6
|
+
|
|
7
|
+
In this exercise you have to create some code that counts the number of
|
|
8
|
+
mines adjacent to a square and transforms boards like this (where `*`
|
|
9
|
+
indicates a mine):
|
|
10
|
+
|
|
11
|
+
+-----+
|
|
12
|
+
| * * |
|
|
13
|
+
| * |
|
|
14
|
+
| * |
|
|
15
|
+
| |
|
|
16
|
+
+-----+
|
|
17
|
+
|
|
18
|
+
into this:
|
|
19
|
+
|
|
20
|
+
+-----+
|
|
21
|
+
|1*3*1|
|
|
22
|
+
|13*31|
|
|
23
|
+
| 2*2 |
|
|
24
|
+
| 111 |
|
|
25
|
+
+-----+
|
|
26
|
+
|
|
27
|
+
## Running tests
|
|
28
|
+
|
|
29
|
+
In order to run the tests, issue the following command from the exercise
|
|
30
|
+
directory:
|
|
31
|
+
|
|
32
|
+
For running the tests provided, `rebar3` is used as it is the official build and
|
|
33
|
+
dependency management tool for erlang now. Please refer to [the tracks installation
|
|
34
|
+
instructions](http://exercism.io/languages/erlang/installation) on how to do that.
|
|
35
|
+
|
|
36
|
+
In order to run the tests, you can issue the following command from the exercise
|
|
37
|
+
directory.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
$ rebar3 eunit
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Test versioning
|
|
44
|
+
|
|
45
|
+
Each problem defines a macro `TEST_VERSION` in the test file and
|
|
46
|
+
verifies that the solution defines and exports a function `test_version`
|
|
47
|
+
returning that same value.
|
|
48
|
+
|
|
49
|
+
To make tests pass, add the following to your solution:
|
|
50
|
+
|
|
51
|
+
```erlang
|
|
52
|
+
-export([test_version/0]).
|
|
53
|
+
|
|
54
|
+
test_version() ->
|
|
55
|
+
1.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The benefit of this is that reviewers can see against which test version
|
|
59
|
+
an iteration was written if, for example, a previously posted solution
|
|
60
|
+
does not solve the current problem or passes current tests.
|
|
61
|
+
|
|
62
|
+
## Questions?
|
|
63
|
+
|
|
64
|
+
For detailed information about the Erlang track, please refer to the
|
|
65
|
+
[help page](http://exercism.io/languages/erlang) on the Exercism site.
|
|
66
|
+
This covers the basic information on setting up the development
|
|
67
|
+
environment expected by the exercises.
|
|
68
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
%% Erlang compiler options
|
|
2
|
+
{erl_opts, [debug_info]}.
|
|
3
|
+
|
|
4
|
+
{deps, [{erl_exercism, "0.1.2"}]}.
|
|
5
|
+
|
|
6
|
+
{dialyzer, [
|
|
7
|
+
{warnings, [underspecs, no_return]},
|
|
8
|
+
{get_warnings, true},
|
|
9
|
+
{plt_apps, top_level_deps}, % top_level_deps | all_deps
|
|
10
|
+
{plt_extra_apps, []},
|
|
11
|
+
{plt_location, local}, % local | "/my/file/name"
|
|
12
|
+
{plt_prefix, "rebar3"},
|
|
13
|
+
{base_plt_apps, [stdlib, kernel, crypto]},
|
|
14
|
+
{base_plt_location, global}, % global | "/my/file/name"
|
|
15
|
+
{base_plt_prefix, "rebar3"}
|
|
16
|
+
]}.
|
|
17
|
+
|
|
18
|
+
%% eunit:test(Tests)
|
|
19
|
+
{eunit_tests, []}.
|
|
20
|
+
%% Options for eunit:test(Tests, Opts)
|
|
21
|
+
{eunit_opts, [verbose]}.
|
|
22
|
+
|
|
23
|
+
%% == xref ==
|
|
24
|
+
|
|
25
|
+
{xref_warnings, true}.
|
|
26
|
+
|
|
27
|
+
%% xref checks to run
|
|
28
|
+
{xref_checks, [undefined_function_calls, undefined_functions,
|
|
29
|
+
locals_not_used, exports_not_used,
|
|
30
|
+
deprecated_function_calls, deprecated_functions]}.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
-module(example).
|
|
2
|
+
|
|
3
|
+
-export([annotate/1, test_version/0]).
|
|
4
|
+
|
|
5
|
+
%% no rows
|
|
6
|
+
annotate([]) ->
|
|
7
|
+
[];
|
|
8
|
+
|
|
9
|
+
%% no columns
|
|
10
|
+
annotate(Minefield=[""|_]) ->
|
|
11
|
+
Minefield;
|
|
12
|
+
|
|
13
|
+
%% proper minefield
|
|
14
|
+
annotate(Minefield) ->
|
|
15
|
+
process_minefield(extend(Minefield)).
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
%% surround the actual minefield with non-mines
|
|
19
|
+
%% the rows and columns of the extended minefield will be implicitly reversed
|
|
20
|
+
extend(Minefield=[R|_]) ->
|
|
21
|
+
EdgeRow=[16#20 || _ <- lists:seq(1, length(R)+2)],
|
|
22
|
+
[EdgeRow|extend(Minefield, [EdgeRow])].
|
|
23
|
+
|
|
24
|
+
extend([], Acc) ->
|
|
25
|
+
Acc;
|
|
26
|
+
|
|
27
|
+
extend([Row|More], Acc) ->
|
|
28
|
+
ExtendedRow=[16#20|lists:reverse([16#20|Row])],
|
|
29
|
+
extend(More, [ExtendedRow|Acc]).
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
%% process the (extended) minefield
|
|
33
|
+
%% the rows and columns of the processed minefield will be implicitly reversed,
|
|
34
|
+
%% thereby restoring the original ordering
|
|
35
|
+
%% three rows need to be considered: the previous, the current, and the next
|
|
36
|
+
process_minefield(Minefield) ->
|
|
37
|
+
process_minefield(Minefield, []).
|
|
38
|
+
|
|
39
|
+
%% only two rows left, at end of minefield
|
|
40
|
+
process_minefield([_, _], Acc) ->
|
|
41
|
+
Acc;
|
|
42
|
+
|
|
43
|
+
%% at least 3 rows left, process them
|
|
44
|
+
process_minefield([PrevRow|More=[CurRow, NextRow|_]], Acc) ->
|
|
45
|
+
process_minefield(More, [process_row(PrevRow, CurRow, NextRow)|Acc]).
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
%% process a row of the minefield
|
|
49
|
+
%% three columns of the previous and next rows and two of the current row need to be considered
|
|
50
|
+
process_row(PrevRow, CurRow, NextRow) ->
|
|
51
|
+
process_row(PrevRow, CurRow, NextRow, []).
|
|
52
|
+
|
|
53
|
+
%% only two columns left, at end of row
|
|
54
|
+
process_row([_, _], [_, _], [_, _], Acc) ->
|
|
55
|
+
Acc;
|
|
56
|
+
|
|
57
|
+
%% current element is a mine, don't change it
|
|
58
|
+
process_row([_|MorePrev], [_|MoreCur=[$*|_]], [_|MoreNext], Acc) ->
|
|
59
|
+
process_row(MorePrev, MoreCur, MoreNext, [$*|Acc]);
|
|
60
|
+
|
|
61
|
+
%% current element is not a mine, count surrounding mines, translate to character
|
|
62
|
+
process_row([PrevPrev|MorePrev=[PrevCur, PrevNext|_]], [CurPrev|MoreCur=[_, CurNext|_]], [NextPrev|MoreNext=[NextCur, NextNext|_]], Acc) ->
|
|
63
|
+
N=lists:foldl(
|
|
64
|
+
fun ($*, Count) -> Count+1; (16#20, Count) -> Count end,
|
|
65
|
+
0,
|
|
66
|
+
[PrevPrev, PrevCur, PrevNext, CurPrev, CurNext, NextPrev, NextCur, NextNext]
|
|
67
|
+
),
|
|
68
|
+
process_row(MorePrev, MoreCur, MoreNext, [count_to_char(N)|Acc]).
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
%% translate a count into a character
|
|
72
|
+
count_to_char(0) -> 16#20;
|
|
73
|
+
count_to_char(N) -> $0+N.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
test_version() -> 1.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
%% based on canonical data version 1.1.0
|
|
2
|
+
%% https://raw.githubusercontent.com/exercism/problem-specifications/master/exercises/minesweeper/canonical-data.json
|
|
3
|
+
|
|
4
|
+
-module(minesweeper_tests).
|
|
5
|
+
|
|
6
|
+
-define(TESTED_MODULE, (sut(minesweeper))).
|
|
7
|
+
-define(TEST_VERSION, 1).
|
|
8
|
+
-include_lib("erl_exercism/include/exercism.hrl").
|
|
9
|
+
-include_lib("eunit/include/eunit.hrl").
|
|
10
|
+
|
|
11
|
+
no_rows_test() ->
|
|
12
|
+
Input=[],
|
|
13
|
+
Expected=[],
|
|
14
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
15
|
+
|
|
16
|
+
no_columns_test() ->
|
|
17
|
+
Input=[""],
|
|
18
|
+
Expected=[""],
|
|
19
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
20
|
+
|
|
21
|
+
no_mines_test() ->
|
|
22
|
+
Input=[
|
|
23
|
+
" ",
|
|
24
|
+
" ",
|
|
25
|
+
" "
|
|
26
|
+
],
|
|
27
|
+
Expected=[
|
|
28
|
+
" ",
|
|
29
|
+
" ",
|
|
30
|
+
" "
|
|
31
|
+
],
|
|
32
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
33
|
+
|
|
34
|
+
only_mines_test() ->
|
|
35
|
+
Input=[
|
|
36
|
+
"***",
|
|
37
|
+
"***",
|
|
38
|
+
"***"
|
|
39
|
+
],
|
|
40
|
+
Expected=[
|
|
41
|
+
"***",
|
|
42
|
+
"***",
|
|
43
|
+
"***"
|
|
44
|
+
],
|
|
45
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
46
|
+
|
|
47
|
+
mine_surrounded_by_spaces_test() ->
|
|
48
|
+
Input=[
|
|
49
|
+
" ",
|
|
50
|
+
" * ",
|
|
51
|
+
" "
|
|
52
|
+
],
|
|
53
|
+
Expected=[
|
|
54
|
+
"111",
|
|
55
|
+
"1*1",
|
|
56
|
+
"111"
|
|
57
|
+
],
|
|
58
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
59
|
+
|
|
60
|
+
space_surrounded_by_mines_test() ->
|
|
61
|
+
Input=[
|
|
62
|
+
"***",
|
|
63
|
+
"* *",
|
|
64
|
+
"***"
|
|
65
|
+
],
|
|
66
|
+
Expected=[
|
|
67
|
+
"***",
|
|
68
|
+
"*8*",
|
|
69
|
+
"***"
|
|
70
|
+
],
|
|
71
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
72
|
+
|
|
73
|
+
horizontal_line_test() ->
|
|
74
|
+
Input=[" * * "],
|
|
75
|
+
Expected=["1*2*1"],
|
|
76
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
77
|
+
|
|
78
|
+
horizontal_line_mines_at_edges_test() ->
|
|
79
|
+
Input=["* *"],
|
|
80
|
+
Expected=["*1 1*"],
|
|
81
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
82
|
+
|
|
83
|
+
vertical_line_test() ->
|
|
84
|
+
Input=[
|
|
85
|
+
" ",
|
|
86
|
+
"*",
|
|
87
|
+
" ",
|
|
88
|
+
"*",
|
|
89
|
+
" "
|
|
90
|
+
],
|
|
91
|
+
Expected=[
|
|
92
|
+
"1",
|
|
93
|
+
"*",
|
|
94
|
+
"2",
|
|
95
|
+
"*",
|
|
96
|
+
"1"
|
|
97
|
+
],
|
|
98
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
99
|
+
|
|
100
|
+
vertical_line_mines_at_edges_test() ->
|
|
101
|
+
Input=[
|
|
102
|
+
"*",
|
|
103
|
+
" ",
|
|
104
|
+
" ",
|
|
105
|
+
" ",
|
|
106
|
+
"*"
|
|
107
|
+
],
|
|
108
|
+
Expected=[
|
|
109
|
+
"*",
|
|
110
|
+
"1",
|
|
111
|
+
" ",
|
|
112
|
+
"1",
|
|
113
|
+
"*"
|
|
114
|
+
],
|
|
115
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
116
|
+
|
|
117
|
+
cross_test() ->
|
|
118
|
+
Input=[
|
|
119
|
+
" * ",
|
|
120
|
+
" * ",
|
|
121
|
+
"*****",
|
|
122
|
+
" * ",
|
|
123
|
+
" * "
|
|
124
|
+
],
|
|
125
|
+
Expected=[
|
|
126
|
+
" 2*2 ",
|
|
127
|
+
"25*52",
|
|
128
|
+
"*****",
|
|
129
|
+
"25*52",
|
|
130
|
+
" 2*2 "
|
|
131
|
+
],
|
|
132
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
133
|
+
|
|
134
|
+
large_minefield_test() ->
|
|
135
|
+
Input=[
|
|
136
|
+
" * * ",
|
|
137
|
+
" * ",
|
|
138
|
+
" * ",
|
|
139
|
+
" * *",
|
|
140
|
+
" * * ",
|
|
141
|
+
" "
|
|
142
|
+
],
|
|
143
|
+
Expected=[
|
|
144
|
+
"1*22*1",
|
|
145
|
+
"12*322",
|
|
146
|
+
" 123*2",
|
|
147
|
+
"112*4*",
|
|
148
|
+
"1*22*2",
|
|
149
|
+
"111111"
|
|
150
|
+
],
|
|
151
|
+
?assertMatch(Expected, minesweeper:annotate(Input)).
|
|
152
|
+
|
|
153
|
+
version_test() ->
|
|
154
|
+
?assertMatch(?TEST_VERSION, minesweeper:test_version()).
|