trackler 2.0.8.15 → 2.0.8.16
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/common/exercises/clock/canonical-data.json +473 -425
- data/common/exercises/crypto-square/canonical-data.json +105 -95
- data/common/exercises/difference-of-squares/canonical-data.json +76 -62
- data/common/exercises/etl/canonical-data.json +67 -59
- data/common/exercises/meetup/canonical-data.json +859 -762
- data/common/exercises/meetup/description.md +13 -7
- data/common/exercises/minesweeper/canonical-data.json +21 -5
- data/common/exercises/nth-prime/canonical-data.json +23 -16
- data/common/exercises/nucleotide-count/canonical-data.json +49 -41
- data/common/exercises/ocr-numbers/canonical-data.json +204 -183
- data/common/exercises/pascals-triangle/canonical-data.json +38 -27
- data/common/exercises/queen-attack/canonical-data.json +125 -109
- data/common/exercises/rotational-cipher/canonical-data.json +1 -1
- data/common/exercises/triangle/canonical-data.json +103 -74
- data/lib/trackler/version.rb +1 -1
- data/tracks/csharp/docs/TESTS.md +7 -1
- data/tracks/csharp/exercises/{exercises.sln → Exercises.All.sln} +0 -0
- data/tracks/csharp/exercises/Exercises.Default.sln +1433 -0
- data/tracks/csharp/exercises/Exercises.Refactoring.sln +61 -0
- data/tracks/csharp/exercises/acronym/AcronymTest.cs +35 -11
- data/tracks/csharp/exercises/parallel-letter-frequency/ParallelLetterFrequencyTest.cs +2 -2
- data/tracks/delphi/docs/TESTS.md +2 -2
- data/tracks/elixir/exercises/bowling/bowling.exs +1 -1
- data/tracks/fsharp/docs/LEARNING.md +2 -1
- data/tracks/go/config.json +7 -1
- data/tracks/go/exercises/prime-factors/{primefactors_test.go → prime_factors_test.go} +4 -1
- data/tracks/go/exercises/protein-translation/protein_translation_test.go +6 -6
- data/tracks/go/exercises/pythagorean-triplet/example.go +2 -0
- data/tracks/go/exercises/pythagorean-triplet/pythagorean_triplet_test.go +8 -0
- data/tracks/julia/README.md +2 -0
- data/tracks/julia/config.json +9 -0
- data/tracks/julia/exercises/rotational-cipher/HINTS.md +21 -0
- data/tracks/julia/exercises/rotational-cipher/example.jl +16 -0
- data/tracks/julia/exercises/rotational-cipher/rotational-cipher.jl +0 -0
- data/tracks/julia/exercises/rotational-cipher/runtests.jl +51 -0
- data/tracks/ocaml/config.json +5 -0
- data/tracks/ocaml/exercises/connect/.merlin +3 -0
- data/tracks/ocaml/exercises/connect/Makefile +15 -0
- data/tracks/ocaml/exercises/connect/connect.mli +4 -0
- data/tracks/ocaml/exercises/connect/example.ml +80 -0
- data/tracks/ocaml/exercises/connect/test.ml +121 -0
- data/tracks/ocaml/tools/test-generator/templates/connect/template.ml +23 -0
- data/tracks/python/exercises/all-your-base/all_your_base_test.py +2 -0
- data/tracks/python/exercises/luhn/example.py +5 -8
- data/tracks/python/exercises/luhn/luhn_test.py +34 -24
- data/tracks/ruby/README.md +138 -23
- metadata +16 -4
@@ -0,0 +1,61 @@
|
|
1
|
+
Microsoft Visual Studio Solution File, Format Version 12.00
|
2
|
+
# Visual Studio 15
|
3
|
+
VisualStudioVersion = 15.0.26228.4
|
4
|
+
MinimumVisualStudioVersion = 15.0.26124.0
|
5
|
+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TreeBuilding", "tree-building\TreeBuilding.csproj", "{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}"
|
6
|
+
EndProject
|
7
|
+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ledger", "ledger\Ledger.csproj", "{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}"
|
8
|
+
EndProject
|
9
|
+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Markdown", "markdown\Markdown.csproj", "{78C54755-0602-409D-8058-0AC3C339BF37}"
|
10
|
+
EndProject
|
11
|
+
Global
|
12
|
+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
13
|
+
Debug|Any CPU = Debug|Any CPU
|
14
|
+
Debug|x64 = Debug|x64
|
15
|
+
Debug|x86 = Debug|x86
|
16
|
+
Release|Any CPU = Release|Any CPU
|
17
|
+
Release|x64 = Release|x64
|
18
|
+
Release|x86 = Release|x86
|
19
|
+
EndGlobalSection
|
20
|
+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
21
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
22
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
23
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
24
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Debug|x64.Build.0 = Debug|Any CPU
|
25
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
26
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Debug|x86.Build.0 = Debug|Any CPU
|
27
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
28
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Release|Any CPU.Build.0 = Release|Any CPU
|
29
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Release|x64.ActiveCfg = Release|Any CPU
|
30
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Release|x64.Build.0 = Release|Any CPU
|
31
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Release|x86.ActiveCfg = Release|Any CPU
|
32
|
+
{B0E08B2C-51F8-4E11-9D7C-02F08EAFEAD1}.Release|x86.Build.0 = Release|Any CPU
|
33
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
34
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
35
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
36
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Debug|x64.Build.0 = Debug|Any CPU
|
37
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
38
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Debug|x86.Build.0 = Debug|Any CPU
|
39
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
40
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Release|Any CPU.Build.0 = Release|Any CPU
|
41
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Release|x64.ActiveCfg = Release|Any CPU
|
42
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Release|x64.Build.0 = Release|Any CPU
|
43
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Release|x86.ActiveCfg = Release|Any CPU
|
44
|
+
{4CD21D4F-5DCC-4506-8BDB-292555F43E9B}.Release|x86.Build.0 = Release|Any CPU
|
45
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
46
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
47
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Debug|x64.ActiveCfg = Debug|Any CPU
|
48
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Debug|x64.Build.0 = Debug|Any CPU
|
49
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Debug|x86.ActiveCfg = Debug|Any CPU
|
50
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Debug|x86.Build.0 = Debug|Any CPU
|
51
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
52
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Release|Any CPU.Build.0 = Release|Any CPU
|
53
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Release|x64.ActiveCfg = Release|Any CPU
|
54
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Release|x64.Build.0 = Release|Any CPU
|
55
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Release|x86.ActiveCfg = Release|Any CPU
|
56
|
+
{78C54755-0602-409D-8058-0AC3C339BF37}.Release|x86.Build.0 = Release|Any CPU
|
57
|
+
EndGlobalSection
|
58
|
+
GlobalSection(SolutionProperties) = preSolution
|
59
|
+
HideSolutionNode = FALSE
|
60
|
+
EndGlobalSection
|
61
|
+
EndGlobal
|
@@ -3,20 +3,44 @@ using Xunit;
|
|
3
3
|
public class AcronymTest
|
4
4
|
{
|
5
5
|
[Fact]
|
6
|
-
public void
|
6
|
+
public void Basic()
|
7
7
|
{
|
8
|
-
Assert.Equal(
|
8
|
+
Assert.Equal("PNG", Acronym.Abbreviate("Portable Network Graphics"));
|
9
9
|
}
|
10
10
|
|
11
|
-
[
|
12
|
-
|
13
|
-
[InlineData("Ruby on Rails", "ROR")]
|
14
|
-
[InlineData("HyperText Markup Language", "HTML")]
|
15
|
-
[InlineData("First In, First Out", "FIFO")]
|
16
|
-
[InlineData("PHP: Hypertext Preprocessor", "PHP")]
|
17
|
-
[InlineData("Complementary metal-oxide semiconductor", "CMOS")]
|
18
|
-
public void Phrase_abbreviated_to_acronym(string phrase, string expected)
|
11
|
+
[Fact(Skip = "Remove to run test")]
|
12
|
+
public void Lowercase_words()
|
19
13
|
{
|
20
|
-
Assert.Equal(
|
14
|
+
Assert.Equal("ROR", Acronym.Abbreviate("Ruby on Rails"));
|
15
|
+
}
|
16
|
+
|
17
|
+
[Fact(Skip = "Remove to run test")]
|
18
|
+
public void Camelcase()
|
19
|
+
{
|
20
|
+
Assert.Equal("HTML", Acronym.Abbreviate("HyperText Markup Language"));
|
21
|
+
}
|
22
|
+
|
23
|
+
[Fact(Skip = "Remove to run test")]
|
24
|
+
public void Punctuation()
|
25
|
+
{
|
26
|
+
Assert.Equal("FIFO", Acronym.Abbreviate("First In, First Out"));
|
27
|
+
}
|
28
|
+
|
29
|
+
[Fact(Skip = "Remove to run test")]
|
30
|
+
public void All_caps_words()
|
31
|
+
{
|
32
|
+
Assert.Equal("PHP", Acronym.Abbreviate("PHP: Hypertext Preprocessor"));
|
33
|
+
}
|
34
|
+
|
35
|
+
[Fact(Skip = "Remove to run test")]
|
36
|
+
public void NonAcronymAllCapsWord()
|
37
|
+
{
|
38
|
+
Assert.Equal("GIMP", Acronym.Abbreviate("GNU Image Manipulation Program"));
|
39
|
+
}
|
40
|
+
|
41
|
+
[Fact(Skip = "Remove to run test")]
|
42
|
+
public void Hyphenated()
|
43
|
+
{
|
44
|
+
Assert.Equal("CMOS", Acronym.Abbreviate("Complementary metal-oxide semiconductor"));
|
21
45
|
}
|
22
46
|
}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
using System.Linq;
|
3
3
|
using Xunit;
|
4
4
|
|
5
|
-
public class
|
5
|
+
public class ParallelLetterFrequencyTest
|
6
6
|
{
|
7
7
|
// Poem by Friedrich Schiller. The corresponding music is the European Anthem.
|
8
8
|
private const string OdeAnDieFreude =
|
@@ -118,4 +118,4 @@ public class ParallelLetterParallelLetterFrequency
|
|
118
118
|
Assert.Equal(56, actual['t']);
|
119
119
|
Assert.Equal(2, actual['ü']);
|
120
120
|
}
|
121
|
-
}
|
121
|
+
}
|
data/tracks/delphi/docs/TESTS.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
## Running The Tests
|
2
2
|
|
3
|
-
Exercises that have been fetched using the Exercism.io client are delivered with a minimum of three files: a `readme.md` file, a `.dpr` file, and a `.pas` file. The `.dpr` file is the Delphi project file and the `.pas` file is the test runner. Load the Delphi project by either double clicking on the `.dpr` file or by opening the project from with in Delphi. You will be responsible for creating a new `.pas` file that will contain your solution code that the tests will be run against. Refer to the `readme.md` file for instruction on how to
|
3
|
+
Exercises that have been fetched using the Exercism.io [command line client](http://www.exercism.io/cli) are delivered with a minimum of three files: a `readme.md` file, a `.dpr` file, and a `.pas` file. The `.dpr` file is the Delphi project file and the `.pas` file is the test runner. Load the Delphi project by either double clicking on the `.dpr` file or by opening the project from with in Delphi. You will be responsible for creating a new `.pas` file that will contain your solution code that the tests will be run against. Refer to the `readme.md` file for instruction on how to compile and execute your code.
|
4
4
|
|
5
|
-
All tests have been ignored except the first one for you to work on. To continue, just comment the
|
5
|
+
All tests have been ignored except the first one for you to work on. To continue, just comment the `[Ignore]` attribute on the test to start working on it.
|
6
6
|
|
7
7
|
Make sure [DUnitX](https://github.com/VSoftTechnologies/DUnitX) is installed, if not already installed from the setup above.
|
8
8
|
|
@@ -10,7 +10,7 @@ defmodule Bowling do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
@doc """
|
13
|
-
Records the number of pins knocked down on a single roll. Returns
|
13
|
+
Records the number of pins knocked down on a single roll. Returns `any`
|
14
14
|
unless there is something wrong with the given number of pins, in which
|
15
15
|
case it returns a helpful message.
|
16
16
|
"""
|
@@ -6,8 +6,9 @@
|
|
6
6
|
* The [F# Foundation](http://fsharp.org/) is a non-profit organisation which aim is to promote F#. The website has lots of links to great F# content. Perhaps even more interesting is their [mentorship program](http://fsharp.org/mentorship/index.html), where you can apply to learn F# from an experienced F# mentor.
|
7
7
|
|
8
8
|
### Videos
|
9
|
-
* [F# for the Practical Developer](https://www.youtube.com/watch?v=7z_q06HQLes
|
9
|
+
* [F# for the Practical Developer](https://www.youtube.com/watch?v=7z_q06HQLes) is a nice introduction to F#.
|
10
10
|
* [F# - Why you should give an F](https://www.youtube.com/watch?v=kKkFabSzZvU) has Daniel Chambers give a sweet introduction into F#, neatly highlighting most F#'s features.
|
11
|
+
* In [A tour of F#](https://www.youtube.com/watch?v=15tK48Xes0k), Phillip Carter gives a great introduction to the F# language.
|
11
12
|
* [Dr. Don Syme - Introduction to F#](https://channel9.msdn.com/Series/C9-Lectures-Dr-Don-Syme-Introduction-to-F-/C9-Lectures-Dr-Don-Syme-Introduction-to-F-1-of-3) has Don Syme, the designer of F#, give an introduction to F#.
|
12
13
|
* If you're a C# developer, you might like [F# for C# developers](https://vimeo.com/78908217) by Phil Trelford.
|
13
14
|
* [PluralSight](https://www.pluralsight.com/) has several [great](https://www.pluralsight.com/courses/fsintro) [introduction](https://www.pluralsight.com/courses/fsharp-jumpstart) [courses](https://www.pluralsight.com/courses/fsharp-fundamentals). The downside: PluralSight is a paid service, but you can request a [free trial](https://www.pluralsight.com/pricing).
|
data/tracks/go/config.json
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
"repository": "https://github.com/exercism/xgo",
|
5
5
|
"active": true,
|
6
6
|
"deprecated": [
|
7
|
-
"accumulate",
|
8
7
|
"binary",
|
9
8
|
"bottles",
|
10
9
|
"counter",
|
@@ -80,6 +79,13 @@
|
|
80
79
|
"Filtering"
|
81
80
|
]
|
82
81
|
},
|
82
|
+
{
|
83
|
+
"difficulty": 1,
|
84
|
+
"slug": "accumulate",
|
85
|
+
"topics": [
|
86
|
+
"Lists"
|
87
|
+
]
|
88
|
+
},
|
83
89
|
{
|
84
90
|
"difficulty": 3,
|
85
91
|
"slug": "acronym",
|
@@ -26,10 +26,13 @@ var tests = []struct {
|
|
26
26
|
{93819012551, []int64{11, 9539, 894119}},
|
27
27
|
}
|
28
28
|
|
29
|
-
func
|
29
|
+
func TestTestVersion(t *testing.T) {
|
30
30
|
if testVersion != targetTestVersion {
|
31
31
|
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
32
32
|
}
|
33
|
+
}
|
34
|
+
|
35
|
+
func TestPrimeFactors(t *testing.T) {
|
33
36
|
for _, test := range tests {
|
34
37
|
actual := Factors(test.input)
|
35
38
|
if !reflect.DeepEqual(actual, test.expected) {
|
@@ -44,6 +44,12 @@ var proteinTestCases = []rnaCase{
|
|
44
44
|
{"UGGUGUUAUUAAUGGUUU", []string{"Tryptophan", "Cysteine", "Tyrosine"}},
|
45
45
|
}
|
46
46
|
|
47
|
+
func TestTestVersion(t *testing.T) {
|
48
|
+
if testVersion != targetTestVersion {
|
49
|
+
t.Fatalf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
47
53
|
func TestCodon(t *testing.T) {
|
48
54
|
for _, test := range codonTestCases {
|
49
55
|
actual := FromCodon(test.input)
|
@@ -61,9 +67,3 @@ func TestProtein(t *testing.T) {
|
|
61
67
|
}
|
62
68
|
}
|
63
69
|
}
|
64
|
-
|
65
|
-
func TestTestVersion(t *testing.T) {
|
66
|
-
if testVersion != targetTestVersion {
|
67
|
-
t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
|
68
|
-
}
|
69
|
-
}
|
@@ -24,6 +24,14 @@ import (
|
|
24
24
|
"testing"
|
25
25
|
)
|
26
26
|
|
27
|
+
const targetTestVersion = 1
|
28
|
+
|
29
|
+
func TestTestVersion(t *testing.T) {
|
30
|
+
if testVersion != targetTestVersion {
|
31
|
+
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
27
35
|
var rangeTests = []struct {
|
28
36
|
min, max int
|
29
37
|
ts []Triplet
|
data/tracks/julia/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# Exercism Julia Track
|
2
|
+
|
3
|
+
[](https://gitter.im/exercism/xjulia?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
2
4
|
[](https://travis-ci.org/exercism/xjulia)
|
3
5
|
|
4
6
|
Exercism exercises in Julia.
|
data/tracks/julia/config.json
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
This is a good exercise to experiment with non-standard string literals and metaprogramming.
|
2
|
+
|
3
|
+
A short introduction to non-standard string literals can be found in this [blog post](http://iaindunning.com/blog/julia-unicode.html). A detailed metaprogramming guide can be found in the [manual](http://docs.julialang.org/en/stable/manual/metaprogramming/).
|
4
|
+
|
5
|
+
You can extend your solution by adding the functionality described below. To test your solution, you have to remove the comments at the end of `runtests.jl` before running the tests as usual.
|
6
|
+
|
7
|
+
Bonus A only requires basics as outlined in the blog post. Bonus B requires significantly more knowledge of metaprogramming in Julia.
|
8
|
+
|
9
|
+
## Bonus A
|
10
|
+
Implement a string literal that acts as `ROT13` on the string:
|
11
|
+
```julia
|
12
|
+
R13"abcdefghijklmnopqrstuvwxyz" == "nopqrstuvwxyzabcdefghijklm"
|
13
|
+
```
|
14
|
+
|
15
|
+
## Bonus B
|
16
|
+
Implement string literals `R<i>`, `i = 0, ..., 26`, that shift the string for `i` values:
|
17
|
+
```julia
|
18
|
+
R0"Hello, World!" == "Hello, World!"
|
19
|
+
R4"Testing 1 2 3 testing" == "Xiwxmrk 1 2 3 xiwxmrk"
|
20
|
+
R13"abcdefghijklmnopqrstuvwxyz" == "nopqrstuvwxyzabcdefghijklm"
|
21
|
+
```
|
@@ -0,0 +1,16 @@
|
|
1
|
+
function rotate(n::Int, c::Char)
|
2
|
+
if c in 'a':'z'
|
3
|
+
c = 'a' + (c - 'a' + n) % 26
|
4
|
+
elseif c in 'A':'Z'
|
5
|
+
c = 'A' + (c - 'A' + n) % 26
|
6
|
+
end
|
7
|
+
return c
|
8
|
+
end
|
9
|
+
|
10
|
+
rotate(n::Int, s::String) = join(rotate(n, c) for c in s)
|
11
|
+
|
12
|
+
for n in 0:26
|
13
|
+
eval( :(macro $(Symbol(:R, n, :_str))(s::String)
|
14
|
+
:(rotate($$n, $s))
|
15
|
+
end))
|
16
|
+
end
|
File without changes
|
@@ -0,0 +1,51 @@
|
|
1
|
+
using Base.Test
|
2
|
+
|
3
|
+
include("rotational-cipher.jl")
|
4
|
+
|
5
|
+
@testset "rotate function" begin
|
6
|
+
@testset "rotate by n" begin
|
7
|
+
@testset "no wrap" begin
|
8
|
+
@test rotate(1, "a") == "b"
|
9
|
+
@test rotate(1, 'a') == 'b'
|
10
|
+
@test rotate(13, "m") == "z"
|
11
|
+
@test rotate(13, 'm') == 'z'
|
12
|
+
end
|
13
|
+
@testset "wrap around" begin
|
14
|
+
@test rotate(13, "n") == "a"
|
15
|
+
@test rotate(13, 'n') == 'a'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
@testset "full rotation" begin
|
20
|
+
@test rotate(26, "a") == "a"
|
21
|
+
@test rotate(26, 'a') == 'a'
|
22
|
+
@test rotate(0, "a") == "a"
|
23
|
+
@test rotate(0, 'a') == 'a'
|
24
|
+
end
|
25
|
+
|
26
|
+
@testset "full strings" begin
|
27
|
+
@test rotate(5, "OMG") == "TRL"
|
28
|
+
@test rotate(5, "O M G") == "T R L"
|
29
|
+
@test rotate(4, "Testing 1 2 3 testing") == "Xiwxmrk 1 2 3 xiwxmrk"
|
30
|
+
@test rotate(21, "Let's eat, Grandma!") == "Gzo'n zvo, Bmviyhv!"
|
31
|
+
@test rotate(13, "The quick brown fox jumps over the lazy dog.") == "Gur dhvpx oebja sbk whzcf bire gur ynml qbt."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
36
|
+
# Additional exercises #
|
37
|
+
# Remove the comments for the optional bonus exercises from HINTS.md #
|
38
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
39
|
+
|
40
|
+
# Bonus A
|
41
|
+
# @testset "string literal R13" begin
|
42
|
+
# @test R13"The quick brown fox jumps over the lazy dog." == "Gur dhvpx oebja sbk whzcf bire gur ynml qbt."
|
43
|
+
# end
|
44
|
+
|
45
|
+
# Bonus B
|
46
|
+
# @testset "string literals" begin
|
47
|
+
# @test R5"OMG" == "TRL"
|
48
|
+
# @test R4"Testing 1 2 3 testing" == "Xiwxmrk 1 2 3 xiwxmrk"
|
49
|
+
# @test R21"Let's eat, Grandma!" == "Gzo'n zvo, Bmviyhv!"
|
50
|
+
# @test R13"The quick brown fox jumps over the lazy dog." == "Gur dhvpx oebja sbk whzcf bire gur ynml qbt."
|
51
|
+
# end
|
data/tracks/ocaml/config.json
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
test: test.native
|
2
|
+
@./test.native
|
3
|
+
|
4
|
+
test.native: *.ml *.mli
|
5
|
+
@corebuild -r -quiet -pkg oUnit test.native
|
6
|
+
|
7
|
+
main.byte: clean
|
8
|
+
@corebuild -r -quiet main.byte
|
9
|
+
|
10
|
+
clean:
|
11
|
+
rm -rf _build
|
12
|
+
rm -f test.native
|
13
|
+
rm -f main.byte
|
14
|
+
|
15
|
+
.PHONY: clean
|
@@ -0,0 +1,80 @@
|
|
1
|
+
open Core.Std
|
2
|
+
|
3
|
+
type player = O | X
|
4
|
+
type cell = O | X | Empty
|
5
|
+
|
6
|
+
module IntTuple = struct
|
7
|
+
type t = int * int
|
8
|
+
|
9
|
+
let compare (x0, y0) (x1, y1) =
|
10
|
+
match Int.compare x0 x1 with
|
11
|
+
0 -> Int.compare y0 y1
|
12
|
+
| c -> c
|
13
|
+
|
14
|
+
let t_of_sexp tuple = Tuple2.t_of_sexp Int.t_of_sexp Int.t_of_sexp tuple
|
15
|
+
let sexp_of_t tuple = Tuple2.sexp_of_t Int.sexp_of_t Int.sexp_of_t tuple
|
16
|
+
end
|
17
|
+
|
18
|
+
module IntIntSet = Set.Make(IntTuple)
|
19
|
+
|
20
|
+
let (>|>) f g = Fn.compose g f
|
21
|
+
|
22
|
+
let to_matrix (b: string list): cell array array =
|
23
|
+
let to_cell = function
|
24
|
+
| 'X' -> Some X
|
25
|
+
| 'O' -> Some O
|
26
|
+
| '.' -> Some Empty
|
27
|
+
| _ -> None in
|
28
|
+
List.map b ~f:(String.to_list >|> List.filter_map ~f:to_cell >|> Array.of_list) |> Array.of_list
|
29
|
+
|
30
|
+
let neighbouring_positions rows cols (r, c): (int * int) list =
|
31
|
+
let deltas = [
|
32
|
+
-1,0; -1,1;
|
33
|
+
0,-1; 0,1;
|
34
|
+
1,-1; 1,0;
|
35
|
+
] in
|
36
|
+
List.filter_map deltas ~f:(fun (dr, dc) ->
|
37
|
+
if r + dr < 0 || r + dr >= rows || c + dc < 0 || c + dc >= cols
|
38
|
+
then None
|
39
|
+
else Some (r+dr, c+dc)
|
40
|
+
)
|
41
|
+
|
42
|
+
let neighbours board rows cols (r,c) =
|
43
|
+
let cell = board.(r).(c) in
|
44
|
+
let positions = neighbouring_positions rows cols (r,c) in
|
45
|
+
List.filter positions ~f:(fun (r1,c1) -> cell = board.(r1).(c1))
|
46
|
+
|
47
|
+
let search successors initial ~matches =
|
48
|
+
let rec go visited node =
|
49
|
+
if matches node then (true, visited)
|
50
|
+
else
|
51
|
+
if not (Set.mem visited node) then
|
52
|
+
begin
|
53
|
+
let visited = Set.add visited node in
|
54
|
+
let successor_nodes = successors node in
|
55
|
+
if List.is_empty successor_nodes
|
56
|
+
then (false, visited)
|
57
|
+
else
|
58
|
+
List.fold_left successor_nodes
|
59
|
+
~f:(fun (fnd, v) n -> if fnd then (true, v) else go v n)
|
60
|
+
~init:(false, visited)
|
61
|
+
end
|
62
|
+
else (false, visited)
|
63
|
+
in
|
64
|
+
Array.exists initial ~f:(go (IntIntSet.empty) >|> fst)
|
65
|
+
|
66
|
+
let connect board: player option =
|
67
|
+
let board = to_matrix board in
|
68
|
+
let rows = Array.length board in
|
69
|
+
let cols = Array.length board.(0) in
|
70
|
+
let search = search (neighbours board rows cols) in
|
71
|
+
let initials_x = Array.filter_mapi board ~f:(fun row cell -> if cell.(0) = X then Some (row, 0) else None) in
|
72
|
+
if search initials_x ~matches:(fun (r,c) -> (c = cols - 1) && board.(r).(c) = X)
|
73
|
+
then Some X
|
74
|
+
else
|
75
|
+
begin
|
76
|
+
let initials_o = Array.filter_mapi board.(0) ~f:(fun col cell -> if cell = O then Some (0, col) else None) in
|
77
|
+
if search initials_o ~matches:(fun (r,c) -> (r = rows - 1) && board.(r).(c) = O)
|
78
|
+
then Some O
|
79
|
+
else None
|
80
|
+
end
|