trackler 2.0.5.7 → 2.0.5.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/book-store/canonical-data.json +106 -0
- data/common/exercises/phone-number/canonical-data.json +57 -0
- data/lib/trackler/version.rb +1 -1
- data/tracks/elm/exercises/accumulate/package.json +1 -1
- data/tracks/elm/exercises/allergies/package.json +1 -1
- data/tracks/elm/exercises/anagram/package.json +1 -1
- data/tracks/elm/exercises/atbash-cipher/package.json +1 -1
- data/tracks/elm/exercises/bob/package.json +1 -1
- data/tracks/elm/exercises/difference-of-squares/package.json +1 -1
- data/tracks/elm/exercises/gigasecond/package.json +1 -1
- data/tracks/elm/exercises/grade-school/package.json +1 -1
- data/tracks/elm/exercises/hamming/package.json +1 -1
- data/tracks/elm/exercises/hello-world/package.json +1 -1
- data/tracks/elm/exercises/largest-series-product/package.json +1 -1
- data/tracks/elm/exercises/leap/package.json +1 -1
- data/tracks/elm/exercises/list-ops/package.json +1 -1
- data/tracks/elm/exercises/nucleotide-count/package.json +1 -1
- data/tracks/elm/exercises/pangram/package.json +1 -1
- data/tracks/elm/exercises/phone-number/package.json +1 -1
- data/tracks/elm/exercises/raindrops/package.json +1 -1
- data/tracks/elm/exercises/rna-transcription/package.json +1 -1
- data/tracks/elm/exercises/robot-simulator/package.json +1 -1
- data/tracks/elm/exercises/roman-numerals/package.json +1 -1
- data/tracks/elm/exercises/run-length-encoding/package.json +1 -1
- data/tracks/elm/exercises/say/package.json +1 -1
- data/tracks/elm/exercises/scrabble-score/package.json +1 -1
- data/tracks/elm/exercises/series/package.json +1 -1
- data/tracks/elm/exercises/space-age/package.json +1 -1
- data/tracks/elm/exercises/strain/package.json +1 -1
- data/tracks/elm/exercises/sublist/package.json +1 -1
- data/tracks/elm/exercises/sum-of-multiples/package.json +1 -1
- data/tracks/elm/exercises/triangle/package.json +1 -1
- data/tracks/elm/exercises/word-count/package.json +1 -1
- data/tracks/go/exercises/house/example.go +58 -28
- data/tracks/go/exercises/house/house_test.go +27 -36
- data/tracks/go/exercises/sum-of-multiples/example.go +9 -10
- data/tracks/go/exercises/sum-of-multiples/sum_of_multiples_test.go +9 -44
- data/tracks/pascal/README.md +9 -5
- data/tracks/pascal/config.json +123 -8
- data/tracks/pascal/docs/ABOUT.md +10 -0
- data/tracks/pascal/docs/INSTALLATION.md +18 -0
- data/tracks/pascal/docs/LEARNING.md +5 -0
- data/tracks/scala/exercises/bowling/build.sbt +2 -2
- data/tracks/scala/exercises/bowling/src/test/scala/BowlingSuite.scala +26 -104
- data/tracks/scala/exercises/forth/build.sbt +2 -2
- data/tracks/scala/exercises/forth/src/main/scala/Forth.scala +6 -0
- data/tracks/scala/exercises/nucleotide-count/HINTS.md +12 -12
- data/tracks/scala/exercises/nucleotide-count/build.sbt +2 -2
- data/tracks/scala/exercises/nucleotide-count/example.scala +4 -4
- data/tracks/scala/exercises/nucleotide-count/src/main/scala/DNA.scala +6 -0
- metadata +6 -3
- data/tracks/scala/exercises/nucleotide-count/src/main/scala/.keep +0 -0
@@ -1,16 +1,15 @@
|
|
1
1
|
package summultiples
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
}
|
3
|
+
// SumMultiples returns the sum of the multiples of the given divisors
|
4
|
+
// up to, but not including, the given limit.
|
5
|
+
func SumMultiples(limit int, divisors ...int) (sum int) {
|
6
|
+
for i := 1; i < limit; i++ {
|
7
|
+
for _, d := range divisors {
|
8
|
+
if i%d == 0 {
|
9
|
+
sum += i
|
10
|
+
break
|
12
11
|
}
|
13
12
|
}
|
14
|
-
return sum
|
15
13
|
}
|
14
|
+
return
|
16
15
|
}
|
@@ -2,50 +2,26 @@ package summultiples
|
|
2
2
|
|
3
3
|
import "testing"
|
4
4
|
|
5
|
-
var test35 = []struct {
|
6
|
-
limit int
|
7
|
-
sum int
|
8
|
-
}{
|
9
|
-
{1, 0},
|
10
|
-
{4, 3},
|
11
|
-
{10, 23},
|
12
|
-
{100, 2318},
|
13
|
-
{1000, 233168},
|
14
|
-
}
|
15
|
-
|
16
5
|
var varTests = []struct {
|
17
6
|
divisors []int
|
18
7
|
limit int
|
19
8
|
sum int
|
20
9
|
}{
|
10
|
+
{[]int{3, 5}, 1, 0},
|
11
|
+
{[]int{3, 5}, 4, 3},
|
12
|
+
{[]int{3, 5}, 10, 23},
|
13
|
+
{[]int{3, 5}, 100, 2318},
|
14
|
+
{[]int{3, 5}, 1000, 233168},
|
21
15
|
{[]int{7, 13, 17}, 20, 51},
|
22
16
|
{[]int{43, 47}, 10000, 2203160},
|
23
17
|
{[]int{5, 10, 12}, 10000, 13331672},
|
24
18
|
{[]int{1, 1}, 10000, 49995000},
|
25
|
-
// Note: The following test case deviates from the README.
|
26
|
-
// The README specifies some rather odd defaults, whereas
|
27
|
-
// this has the more logical approach of not implementing any
|
28
|
-
// defaults, which causes the resulting sum to be zero.
|
29
|
-
// See discussion in:
|
30
|
-
// https://github.com/exercism/xgo/issues/256 and
|
31
|
-
// https://github.com/exercism/x-common/issues/198
|
32
19
|
{[]int{}, 10000, 0},
|
33
20
|
}
|
34
21
|
|
35
|
-
func
|
36
|
-
sum35 := MultipleSummer(3, 5)
|
37
|
-
for _, test := range test35 {
|
38
|
-
s := sum35(test.limit)
|
39
|
-
if s != test.sum {
|
40
|
-
t.Fatalf("Sum to %d returned %d, want %d.", test.limit, s, test.sum)
|
41
|
-
}
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
func TestVar(t *testing.T) {
|
22
|
+
func TestSumMultiples(t *testing.T) {
|
46
23
|
for _, test := range varTests {
|
47
|
-
|
48
|
-
s := sv(test.limit)
|
24
|
+
s := SumMultiples(test.limit, test.divisors...)
|
49
25
|
if s != test.sum {
|
50
26
|
t.Fatalf("Sum of multiples of %v to %d returned %d, want %d.",
|
51
27
|
test.divisors, test.limit, s, test.sum)
|
@@ -53,21 +29,10 @@ func TestVar(t *testing.T) {
|
|
53
29
|
}
|
54
30
|
}
|
55
31
|
|
56
|
-
func
|
57
|
-
sum35 := MultipleSummer(3, 5)
|
58
|
-
b.ResetTimer() // bench just the sum function
|
59
|
-
for i := 0; i < b.N; i++ {
|
60
|
-
for _, test := range test35 {
|
61
|
-
sum35(test.limit)
|
62
|
-
}
|
63
|
-
}
|
64
|
-
}
|
65
|
-
|
66
|
-
func BenchmarkVar(b *testing.B) {
|
67
|
-
// bench combined time to bind sum function and call it.
|
32
|
+
func BenchmarkSumMultiples(b *testing.B) {
|
68
33
|
for i := 0; i < b.N; i++ {
|
69
34
|
for _, test := range varTests {
|
70
|
-
|
35
|
+
SumMultiples(test.limit, test.divisors...)
|
71
36
|
}
|
72
37
|
}
|
73
38
|
}
|
data/tracks/pascal/README.md
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
#
|
1
|
+
# xPascal
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
## TODO
|
3
|
+
[](https://travis-ci.org/exercism/xpascal)
|
6
4
|
|
7
|
-
|
5
|
+
Exercism exercises in Pascal.
|
8
6
|
|
9
7
|
## Contributing Guide
|
10
8
|
|
11
9
|
Please see the [contributing guide](https://github.com/exercism/x-common/blob/master/CONTRIBUTING.md).
|
10
|
+
|
11
|
+
## License
|
12
|
+
|
13
|
+
The MIT License (MIT)
|
14
|
+
|
15
|
+
Copyright (c) 2014 Katrina Owen, _@kytrinyx.com
|
data/tracks/pascal/config.json
CHANGED
@@ -3,19 +3,134 @@
|
|
3
3
|
"language": "Pascal",
|
4
4
|
"repository": "https://github.com/exercism/xpascal",
|
5
5
|
"active": false,
|
6
|
-
"test_pattern": "TODO",
|
7
6
|
"exercises": [
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
{
|
8
|
+
"slug": "hello-world",
|
9
|
+
"difficulty": 1,
|
10
|
+
"topics": [
|
11
|
+
"Text formatting",
|
12
|
+
"Optional values"
|
13
|
+
]
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"slug": "bob",
|
17
|
+
"difficulty": 1,
|
18
|
+
"topics": [
|
19
|
+
"Strings",
|
20
|
+
"Control-flow (if-else statements)"
|
21
|
+
]
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"slug": "leap",
|
25
|
+
"difficulty": 1,
|
26
|
+
"topics": [
|
27
|
+
"Integers"
|
28
|
+
]
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"slug": "hamming",
|
32
|
+
"difficulty": 2,
|
33
|
+
"topics": [
|
34
|
+
"Strings",
|
35
|
+
"Filtering"
|
36
|
+
]
|
37
|
+
},
|
38
|
+
{
|
39
|
+
"slug": "bowling",
|
40
|
+
"difficulty": 6,
|
41
|
+
"topics": [
|
42
|
+
"Algorithms",
|
43
|
+
"Control-flow (loops)"
|
44
|
+
]
|
45
|
+
},
|
46
|
+
{
|
47
|
+
"slug": "allergies",
|
48
|
+
"difficulty": 4,
|
49
|
+
"topics": [
|
50
|
+
"Bitwise operations",
|
51
|
+
"Filtering"
|
52
|
+
]
|
53
|
+
},
|
54
|
+
{
|
55
|
+
"slug": "bank-account",
|
56
|
+
"difficulty": 2,
|
57
|
+
"topics": [
|
58
|
+
"Classes"
|
59
|
+
]
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"slug": "beer-song",
|
63
|
+
"difficulty": 3,
|
64
|
+
"topics": [
|
65
|
+
"Text formatting",
|
66
|
+
"Algorithms"
|
67
|
+
]
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"slug": "phone-number",
|
71
|
+
"difficulty": 3,
|
72
|
+
"topics": [
|
73
|
+
"Parsing",
|
74
|
+
"Transforming"
|
75
|
+
]
|
76
|
+
},
|
77
|
+
{
|
78
|
+
"slug": "binary-search",
|
79
|
+
"difficulty": 3,
|
80
|
+
"topics": [
|
81
|
+
"Searching",
|
82
|
+
"Arrays"
|
83
|
+
]
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"slug": "book-store",
|
87
|
+
"difficulty": 6
|
88
|
+
},
|
89
|
+
{
|
90
|
+
"slug": "perfect-numbers",
|
91
|
+
"difficulty": 3,
|
92
|
+
"topics": [
|
93
|
+
"Integers"
|
94
|
+
]
|
95
|
+
},
|
96
|
+
{
|
97
|
+
"slug": "nucleotide-count",
|
98
|
+
"difficulty": 2,
|
99
|
+
"topics": [
|
100
|
+
"Dictionaries",
|
101
|
+
"Strings"
|
102
|
+
]
|
103
|
+
},
|
104
|
+
{
|
105
|
+
"slug": "etl",
|
106
|
+
"difficulty": 2,
|
107
|
+
"topics": [
|
108
|
+
"Dictionaries",
|
109
|
+
"Lists",
|
110
|
+
"Transforming"
|
111
|
+
]
|
112
|
+
},
|
113
|
+
{
|
114
|
+
"slug": "binary-search",
|
115
|
+
"difficulty": 3,
|
116
|
+
"topics": [
|
117
|
+
"Searching",
|
118
|
+
"Arrays",
|
119
|
+
"Recursion"
|
120
|
+
]
|
121
|
+
},
|
122
|
+
{
|
123
|
+
"slug": "clock",
|
124
|
+
"difficulty": 3,
|
125
|
+
"topics": [
|
126
|
+
"Time",
|
127
|
+
"Structural equality"
|
128
|
+
]
|
129
|
+
}
|
12
130
|
],
|
13
131
|
"ignored": [
|
14
132
|
"bin",
|
15
133
|
"img",
|
16
134
|
"docs"
|
17
|
-
],
|
18
|
-
"foregone": [
|
19
|
-
|
20
135
|
]
|
21
136
|
}
|
data/tracks/pascal/docs/ABOUT.md
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
## Delphi (programming language) ##
|
2
|
+
*From Wikipedia, the free encyclopedia*
|
3
|
+
|
4
|
+
**Embarcadero Delphi** is a [programming language](https://en.wikipedia.org/wiki/Programming_language) and [software development kit](https://en.wikipedia.org/wiki/Software_development_kit) (SDK) for [desktop](https://en.wikipedia.org/wiki/Graphical_user_interface), [mobile](https://en.wikipedia.org/wiki/Mobile_app), [web](https://en.wikipedia.org/wiki/Web_application), and [console](https://en.wikipedia.org/wiki/Console_application) applications.[[1]](https://en.wikipedia.org/wiki/Delphi_(programming_language)#cite_note-Buchanan2003-1) Delphi's compilers use their own [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) dialect of [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language)) and generate native code for several platforms: Windows ([x86](https://en.wikipedia.org/wiki/IA-32) and [x64](https://en.wikipedia.org/wiki/X86-64)), [OS X](https://en.wikipedia.org/wiki/MacOS) (32-bit only), [iOS](https://en.wikipedia.org/wiki/IOS) (32 and 64-bit) and [Android](https://en.wikipedia.org/wiki/Android_(operating_system)).
|
5
|
+
|
6
|
+
Delphi, part of [RAD Studio](https://en.wikipedia.org/wiki/Delphi_(programming_language)#RAD_Studio), includes a code editor with [Code Insight](https://en.wikipedia.org/wiki/Code_Insight) ([code completion](https://en.wikipedia.org/wiki/Autocomplete#In_source_code_editors)), [Error Insight](https://en.wikipedia.org/wiki/Error_Insight) (real-time error-checking), and other features; [refactoring](https://en.wikipedia.org/wiki/Code_refactoring); a visual forms designer for both [VCL](https://en.wikipedia.org/wiki/Visual_Component_Library) (native Windows) and [FMX](https://en.wikipedia.org/wiki/FireMonkey) (cross-platform, partially native per platform); an integrated debugger for all platforms including mobile; source control ([SVN](https://en.wikipedia.org/wiki/Apache_Subversion), [git](https://en.wikipedia.org/wiki/Git), and [Mercurial](https://en.wikipedia.org/wiki/Mercurial)); and support for third-party plugins. It has strong database support. Delphi is remarkably fast to compile:[[2]](https://en.wikipedia.org/wiki/Delphi_(programming_language)#cite_note-2) unlike any other common languages, including C# and Swift, it is not unusual for a Delphi project of a million lines to compile in a few seconds – one benchmark gave 170,000 lines per second.[[3]](https://en.wikipedia.org/wiki/Delphi_(programming_language)#cite_note-3)[[4]](https://en.wikipedia.org/wiki/Delphi_(programming_language)#cite_note-4) It is under active development, with (in 2016) releases every six months, with new platforms being added approximately every second release.[[5]](https://en.wikipedia.org/wiki/Delphi_(programming_language)#cite_note-5)
|
7
|
+
|
8
|
+
Delphi was originally developed by [Borland](https://en.wikipedia.org/wiki/Borland) as a [rapid application development](https://en.wikipedia.org/wiki/Rapid_application_development) tool for Windows as the successor of [Turbo Pascal](https://en.wikipedia.org/wiki/Turbo_Pascal). Delphi added full object-orientation to the existing language, and since then the language has grown and supports many other modern language features, including generics and anonymous methods, as well as unusual features such as inbuilt string types and native COM support. Delphi and its [C++](https://en.wikipedia.org/wiki/C%2B%2B) counterpart, [C++ Builder](https://en.wikipedia.org/wiki/C%2B%2BBuilder), share many core components, notably the IDE, the [Visual Component Library](https://en.wikipedia.org/wiki/Visual_Component_Library) (VCL), and much of the [RTL](https://en.wikipedia.org/wiki/Runtime_library), and are compatible with each other: C++ Builder 6 and onwards can consume Delphi-language files and C++ in the one project, and packages compiled with C++ Builder written in C++ can be used from within Delphi. In 2007, the products were released jointly as RAD Studio. [RAD Studio](https://en.wikipedia.org/wiki/Delphi_(programming_language)#RAD_Studio) is a shared host for Delphi and C++Builder, and can be purchased with either or both.
|
9
|
+
|
10
|
+
In 2006, Borland’s developer tools section were transferred from Borland to a wholly owned subsidiary known as [CodeGear](https://en.wikipedia.org/wiki/CodeGear), which was sold to [Embarcadero Technologies](https://en.wikipedia.org/wiki/Embarcadero_Technologies) in 2008. In 2015, Embarcadero was purchased by Idera, but the Embarcadero mark was retained for the developer tools division.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Installing Delphi and DUnitX Testing Framework #
|
2
|
+
### Windows ###
|
3
|
+
|
4
|
+
30 day free trial of Embarcadero's RAD Studio or Delphi may be downloaded from [here](https://www.embarcadero.com/products?utm_source=google&utm_medium=cpc&utm_campaign=brand&utm_content=brand&utm_embarcadero&gclid=CjwKEAiAp97CBRDr2Oyl-faxqRMSJABx4kh9V8bOEuG0CznQ9AGToIyuKeTzvevljmHTboYXk4n6OxoC4Frw_wcB). Follow installation instructions included with the product.
|
5
|
+
|
6
|
+
### Non-Windows based Operating Systems ###
|
7
|
+
|
8
|
+
Sorry, Delphi does not run natively on any other operating systems. However it should be possible to install Delphi into a virtual machine which is running Windows.
|
9
|
+
|
10
|
+
|
11
|
+
### Installing DUnitX Test Framework ###
|
12
|
+
With Delphi successfully installed and working correctly please follow these steps for retrieving and installing DUnitX.
|
13
|
+
|
14
|
+
- DUnitX is an open source project by [VSoftTechnologies](https://www.github.com/VSoftTechnologies). The DUnitX github repo is available [here](https://github.com/VSoftTechnologies/DUnitX).
|
15
|
+
- It is best to fork the repo and then clone or otherwise download the fork to your local machine.
|
16
|
+
- Step-by-step instructions on how to install DUnitX into Delphi have been posted by Vincent Parrett in a blog post located [here](https://www.finalbuilder.com/resources/blogs/postid/702/dunitx-has-a-wizard).
|
17
|
+
|
18
|
+
*Note: It is assumed that Delphi versions XE and higher are being utilized by the student.*
|
@@ -0,0 +1,5 @@
|
|
1
|
+
Exercism provides exercises and feedback but can be difficult to jump into for those learning Pascal for the first time. These resources can help you get started:
|
2
|
+
|
3
|
+
* [Pascal Tutorial](https://www.tutorialspoint.com/pascal/index.htm) looks like a good place to get your feet we with Pascal if you have zero experience with this language. You do not need Delphi to complete the exercises covered in this tutorial. This may be a good place to practice up before jumping in to the exercises here, which do require Delphi to complete.
|
4
|
+
* [Pascal-Programming.info](http://www.pascal-programming.info/index.php) also appears to have a good tutorial for newcomers to the language.
|
5
|
+
* There are many more sources online for learning Pascal, too many to list here.
|
@@ -1,3 +1,3 @@
|
|
1
|
-
scalaVersion := "2.
|
1
|
+
scalaVersion := "2.12.1"
|
2
2
|
|
3
|
-
libraryDependencies += "org.scalatest"
|
3
|
+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
|
@@ -4,234 +4,156 @@ class BowlingSuite extends FunSuite with Matchers {
|
|
4
4
|
// returns the final score of a bowling game
|
5
5
|
test("should be able to score a game with all zeros") {
|
6
6
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
7
|
-
score
|
8
|
-
case Right(n) => assert(n == 0)
|
9
|
-
case Left(_) => fail("should be able to score a game with all zeros")
|
10
|
-
}
|
7
|
+
score should be (Right(0))
|
11
8
|
}
|
12
9
|
|
13
10
|
test("should be able to score a game with no strikes or spares") {
|
14
11
|
pending
|
15
12
|
val score = List(3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
16
|
-
score
|
17
|
-
case Right(n) => assert(n == 90)
|
18
|
-
case Left(_) => fail("should be able to score a game with no strikes or spares")
|
19
|
-
}
|
13
|
+
score should be (Right(90))
|
20
14
|
}
|
21
15
|
|
22
16
|
test("a spare followed by zeros is worth ten points") {
|
23
17
|
pending
|
24
18
|
val score = List(6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
25
|
-
score
|
26
|
-
case Right(n) => assert(n == 10)
|
27
|
-
case Left(_) => fail("a spare followed by zeros is worth ten points")
|
28
|
-
}
|
19
|
+
score should be (Right(10))
|
29
20
|
}
|
30
21
|
|
31
22
|
test("points scored in the roll after a spare are counted twice") {
|
32
23
|
pending
|
33
24
|
val score = List(6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
34
|
-
score
|
35
|
-
case Right(n) => assert(n == 16)
|
36
|
-
case Left(_) => fail("points scored in the roll after a spare are counted twice")
|
37
|
-
}
|
25
|
+
score should be (Right(16))
|
38
26
|
}
|
39
27
|
|
40
28
|
test("consecutive spares each get a one roll bonus") {
|
41
29
|
pending
|
42
30
|
val score = List(5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
43
|
-
score
|
44
|
-
case Right(n) => assert(n == 31)
|
45
|
-
case Left(_) => fail("consecutive spares each get a one roll bonus")
|
46
|
-
}
|
31
|
+
score should be (Right(31))
|
47
32
|
}
|
48
33
|
|
49
34
|
test("a spare in the last frame gets a one roll bonus that is counted once") {
|
50
35
|
pending
|
51
36
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
52
|
-
score
|
53
|
-
case Right(n) => assert(n == 17)
|
54
|
-
case Left(_) => fail("a spare in the last frame gets a one roll bonus that is counted once")
|
55
|
-
}
|
37
|
+
score should be (Right(17))
|
56
38
|
}
|
57
39
|
|
58
40
|
test("a strike earns ten points in a frame with a single roll") {
|
59
41
|
pending
|
60
42
|
val score = List(10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
61
|
-
score
|
62
|
-
case Right(n) => assert(n == 10)
|
63
|
-
case Left(_) => fail("a strike earns ten points in a frame with a single roll")
|
64
|
-
}
|
43
|
+
score should be (Right(10))
|
65
44
|
}
|
66
45
|
|
67
46
|
test("points scored in the two rolls after a strike are counted twice as a bonus") {
|
68
47
|
pending
|
69
48
|
val score = List(10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
70
|
-
score
|
71
|
-
case Right(n) => assert(n == 26)
|
72
|
-
case Left(_) => fail("points scored in the two rolls after a strike are counted twice as a bonus")
|
73
|
-
}
|
49
|
+
score should be (Right(26))
|
74
50
|
}
|
75
51
|
|
76
52
|
test("consecutive strikes each get the two roll bonus") {
|
77
53
|
pending
|
78
54
|
val score = List(10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
79
|
-
score
|
80
|
-
case Right(n) => assert(n == 81)
|
81
|
-
case Left(_) => fail("consecutive strikes each get the two roll bonus")
|
82
|
-
}
|
55
|
+
score should be (Right(81))
|
83
56
|
}
|
84
57
|
|
85
58
|
test("a strike in the last frame gets a two roll bonus that is counted once") {
|
86
59
|
pending
|
87
60
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
88
|
-
score
|
89
|
-
case Right(n) => assert(n == 18)
|
90
|
-
case Left(_) => fail("a strike in the last frame gets a two roll bonus that is counted once")
|
91
|
-
}
|
61
|
+
score should be (Right(18))
|
92
62
|
}
|
93
63
|
|
94
64
|
test("rolling a spare with the two roll bonus does not get a bonus roll") {
|
95
65
|
pending
|
96
66
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
97
|
-
score
|
98
|
-
case Right(n) => assert(n == 20)
|
99
|
-
case Left(_) => fail("rolling a spare with the two roll bonus does not get a bonus roll")
|
100
|
-
}
|
67
|
+
score should be (Right(20))
|
101
68
|
}
|
102
69
|
|
103
70
|
test("strikes with the two roll bonus do not get bonus rolls") {
|
104
71
|
pending
|
105
72
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
106
|
-
score
|
107
|
-
case Right(n) => assert(n == 30)
|
108
|
-
case Left(_) => fail("strikes with the two roll bonus do not get bonus rolls")
|
109
|
-
}
|
73
|
+
score should be (Right(30))
|
110
74
|
}
|
111
75
|
|
112
76
|
test("a strike with the one roll bonus after a spare in the last frame does not get a bonus") {
|
113
77
|
pending
|
114
78
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
115
|
-
score
|
116
|
-
case Right(n) => assert(n == 20)
|
117
|
-
case Left(_) => fail("a strike with the one roll bonus after a spare in the last frame does not get a bonus")
|
118
|
-
}
|
79
|
+
score should be (Right(20))
|
119
80
|
}
|
120
81
|
|
121
82
|
test("all strikes is a perfect game") {
|
122
83
|
pending
|
123
84
|
val score = List(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
124
|
-
score
|
125
|
-
case Right(n) => assert(n == 300)
|
126
|
-
case Left(_) => fail("all strikes is a perfect game")
|
127
|
-
}
|
85
|
+
score should be (Right(300))
|
128
86
|
}
|
129
87
|
|
130
88
|
test("rolls can not score negative points") {
|
131
89
|
pending
|
132
90
|
val score = List(-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
133
|
-
score
|
134
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
135
|
-
case Left(_) =>
|
136
|
-
}
|
91
|
+
score.isLeft should be (true)
|
137
92
|
}
|
138
93
|
|
139
94
|
test("a roll can not score more than 10 points") {
|
140
95
|
pending
|
141
96
|
val score = List(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
142
|
-
score
|
143
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
144
|
-
case Left(_) =>
|
145
|
-
}
|
97
|
+
score.isLeft should be (true)
|
146
98
|
}
|
147
99
|
|
148
100
|
test("two rolls in a frame can not score more than 10 points") {
|
149
101
|
pending
|
150
102
|
val score = List(5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
151
|
-
score
|
152
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
153
|
-
case Left(_) =>
|
154
|
-
}
|
103
|
+
score.isLeft should be (true)
|
155
104
|
}
|
156
105
|
|
157
106
|
test("two bonus rolls after a strike in the last frame can not score more than 10 points") {
|
158
107
|
pending
|
159
108
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
160
|
-
score
|
161
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
162
|
-
case Left(_) =>
|
163
|
-
}
|
109
|
+
score.isLeft should be (true)
|
164
110
|
}
|
165
111
|
|
166
112
|
test("two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike") {
|
167
113
|
pending
|
168
114
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
169
|
-
score
|
170
|
-
case Right(n) => assert(n == 26)
|
171
|
-
case Left(_) => fail("two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike")
|
172
|
-
}
|
115
|
+
score should be (Right(26))
|
173
116
|
}
|
174
117
|
|
175
118
|
test("the second bonus rolls after a strike in the last frame can not be a strike if the first one is not a strike") {
|
176
119
|
pending
|
177
120
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
178
|
-
score
|
179
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
180
|
-
case Left(_) =>
|
181
|
-
}
|
121
|
+
score.isLeft should be (true)
|
182
122
|
}
|
183
123
|
|
184
124
|
test("an unstarted game can not be scored") {
|
185
125
|
pending
|
186
126
|
val score = List().foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
187
|
-
score
|
188
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
189
|
-
case Left(_) =>
|
190
|
-
}
|
127
|
+
score.isLeft should be (true)
|
191
128
|
}
|
192
129
|
|
193
130
|
test("an incomplete game can not be scored") {
|
194
131
|
pending
|
195
132
|
val score = List(0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
196
|
-
score
|
197
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
198
|
-
case Left(_) =>
|
199
|
-
}
|
133
|
+
score.isLeft should be (true)
|
200
134
|
}
|
201
135
|
|
202
136
|
test("a game with more than ten frames can not be scored") {
|
203
137
|
pending
|
204
138
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
205
|
-
score
|
206
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
207
|
-
case Left(_) =>
|
208
|
-
}
|
139
|
+
score.isLeft should be (true)
|
209
140
|
}
|
210
141
|
|
211
142
|
test("bonus rolls for a strike in the last frame must be rolled before score can be calculated") {
|
212
143
|
pending
|
213
144
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
214
|
-
score
|
215
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
216
|
-
case Left(_) =>
|
217
|
-
}
|
145
|
+
score.isLeft should be (true)
|
218
146
|
}
|
219
147
|
|
220
148
|
test("both bonus rolls for a strike in the last frame must be rolled before score can be calculated") {
|
221
149
|
pending
|
222
150
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
223
|
-
score
|
224
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
225
|
-
case Left(_) =>
|
226
|
-
}
|
151
|
+
score.isLeft should be (true)
|
227
152
|
}
|
228
153
|
|
229
154
|
test("bonus roll for a spare in the last frame must be rolled before score can be calculated") {
|
230
155
|
pending
|
231
156
|
val score = List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3).foldLeft(Bowling())((acc, roll) => acc.roll(roll)).score()
|
232
|
-
score
|
233
|
-
case Right(_) => fail("Unexpected score returned. Failure expected")
|
234
|
-
case Left(_) =>
|
235
|
-
}
|
157
|
+
score.isLeft should be (true)
|
236
158
|
}
|
237
159
|
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
scalaVersion := "2.
|
1
|
+
scalaVersion := "2.12.1"
|
2
2
|
|
3
3
|
|
4
|
-
libraryDependencies += "org.scalatest"
|
4
|
+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
|
5
5
|
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.4"
|
@@ -3,10 +3,10 @@ A common use of `Either` is to indicate a computation that may possibly result i
|
|
3
3
|
(if the actual error is of no interest then the simpler `Option` type might be a better choice).
|
4
4
|
In the absence of an error the result is usually a `Right` (mnemonic: the "right" value)
|
5
5
|
whereas an error is a `Left`, for example a `Left[String]` containing an error message.
|
6
|
-
Note that in Scala `Either` is
|
7
|
-
If you are unfamiliar with `Either` you may read [this tutorial](http://danielwestheide.com/blog/2013/01/02/the-neophytes-guide-to-scala-part-7-the-either-type.html).
|
8
|
-
`Either`
|
9
|
-
|
6
|
+
Note that in Scala 2.12 `Either` is right-biased by default, so it works as expected for operations like `filter`, `map`, `flatMap` or in a for-comprehension.
|
7
|
+
If you are unfamiliar with `Either` you may read [this tutorial](http://danielwestheide.com/blog/2013/01/02/the-neophytes-guide-to-scala-part-7-the-either-type.html). But be aware that this tutorial is about Scala versions prior to 2.12. For Scala 2.12 you can safely ignore `RightProjection` and omit `.right`.
|
8
|
+
`Either` is a so-called [Monad](https://en.wikipedia.org/wiki/Monad_(functional_programming)) which covers a "computational aspect",
|
9
|
+
in this case error handling.
|
10
10
|
Proper use of Monads can result in very concise yet elegant
|
11
11
|
and readable code. Improper use can easily result in the contrary.
|
12
12
|
Watch [this video](https://www.youtube.com/watch?v=Mw_Jnn_Y5iA) to learn more.
|
@@ -20,7 +20,7 @@ better have
|
|
20
20
|
```scala
|
21
21
|
def add1(x: Int): Int = x + 1
|
22
22
|
```
|
23
|
-
(there is `
|
23
|
+
(there is `Either.map` to apply such simple functions,
|
24
24
|
so you don't have to clutter them with `Either`).
|
25
25
|
2. Don't "unwrap" if you don't really need to.
|
26
26
|
Often there are built-in functions for your purpose. Indicators of premature
|
@@ -46,16 +46,16 @@ val xo: Either[String, Int] = ...
|
|
46
46
|
val yo: Either[String, Int] = ...
|
47
47
|
val zo: Either[String, Int] = ...
|
48
48
|
|
49
|
-
xo.
|
50
|
-
yo.
|
51
|
-
zo.
|
52
|
-
|
49
|
+
xo.flatMap(x =>
|
50
|
+
yo.flatMap(y =>
|
51
|
+
zo.map(z =>
|
52
|
+
x + y + z)))
|
53
53
|
```
|
54
54
|
better have
|
55
55
|
```scala
|
56
56
|
for {
|
57
|
-
x <- xo
|
58
|
-
y <- yo
|
59
|
-
z <- zo
|
57
|
+
x <- xo
|
58
|
+
y <- yo
|
59
|
+
z <- zo
|
60
60
|
} yield x + y + z
|
61
61
|
```
|
@@ -1,3 +1,3 @@
|
|
1
|
-
scalaVersion := "2.
|
1
|
+
scalaVersion := "2.12.1"
|
2
2
|
|
3
|
-
libraryDependencies += "org.scalatest"
|
3
|
+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
|