trackler 2.0.8.15 → 2.0.8.16
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Join the chat at https://gitter.im/exercism/xjulia](https://badges.gitter.im/exercism/xjulia.svg)](https://gitter.im/exercism/xjulia?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
2
4
|
[![Build Status](https://travis-ci.org/exercism/xjulia.svg?branch=master)](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
|