trackler 2.0.8.10 → 2.0.8.11
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/palindrome-products/description.md +1 -1
- data/lib/trackler/version.rb +1 -1
- data/tracks/delphi/exercises/bowling/uBowlingExample.pas +52 -23
- data/tracks/delphi/exercises/bowling/uBowlingTests.pas +237 -46
- data/tracks/go/exercises/forth/example.go +36 -37
- data/tracks/go/exercises/kindergarten-garden/kindergarten_garden_test.go +2 -2
- data/tracks/java/exercises/allergies/src/test/java/AllergiesTest.java +2 -0
- data/tracks/scala/config.json +10 -0
- data/tracks/scala/exercises/simple-linked-list/build.sbt +3 -0
- data/tracks/scala/exercises/simple-linked-list/example.scala +95 -0
- data/tracks/scala/exercises/simple-linked-list/src/main/scala/SimpleLinkedList.scala +8 -0
- data/tracks/scala/exercises/simple-linked-list/src/test/scala/SimpleLinkedListTest.scala +108 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7985975e695c967206c6399587638d7b92f6ddeb
|
4
|
+
data.tar.gz: f605cb15bcc556c8f153ebf0aa71768b773709c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f6cd5026c972237c9495b8acd567fa1ac65fc949bcf2da45c797526fe5057cea00c78bd433f840c8003da55f729e675c184a65d4d6510aa589f31288b22350f
|
7
|
+
data.tar.gz: 8687e2946dec0948f8a7800850103074d894c24aba6d92a530ea452672788f7014abf9a3e5d03fcffb619a5e1cbd845f51784451eaad4444a0493c7240a40ba9
|
@@ -27,4 +27,4 @@ The largest product is `9`. It's factors are `(1, 9)`, `(3, 3)`, and `(9, 1)`.
|
|
27
27
|
Given the range `[10, 99]` (both inclusive)...
|
28
28
|
|
29
29
|
The smallest palindrome product is `121`. It's factors are `(11, 11)`.
|
30
|
-
The largest palindrome product is `9009`. It's factors are `(
|
30
|
+
The largest palindrome product is `9009`. It's factors are `(91, 99)` and `(99, 91)`.
|
data/lib/trackler/version.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
unit uBowling;
|
2
2
|
|
3
3
|
interface
|
4
|
-
uses System.Generics.Collections;
|
5
4
|
|
6
5
|
type
|
7
6
|
IBowlingGame = interface(IInvokable)
|
@@ -13,18 +12,22 @@ type
|
|
13
12
|
function NewBowlingGame: IBowlingGame;
|
14
13
|
|
15
14
|
implementation
|
15
|
+
uses System.SysUtils, System.Math, System.Generics.Collections;
|
16
16
|
|
17
17
|
type
|
18
18
|
TBowlingGame = class(TInterfacedObject, IBowlingGame)
|
19
19
|
private
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
var
|
21
|
+
fRolls: TList<integer>;
|
22
|
+
const
|
23
|
+
fNumberOfFrames = 10;
|
24
|
+
fMaximumFrameScore = 10;
|
23
25
|
function IsStrike(aFrameIndex: integer): Boolean;
|
24
26
|
function IsSpare(aFrameIndex: integer): Boolean;
|
25
27
|
function StrikeBonus(aFrameIndex: integer): integer;
|
26
28
|
function SpareBonus(aFrameIndex: integer): integer;
|
27
29
|
function SumOfPinsInFrame(aFrameIndex: integer): integer;
|
30
|
+
function CorrectNumberOfRolls(aFrameIndex: integer): boolean;
|
28
31
|
public
|
29
32
|
constructor create;
|
30
33
|
function Score: integer;
|
@@ -38,8 +41,6 @@ end;
|
|
38
41
|
|
39
42
|
constructor TBowlingGame.create;
|
40
43
|
begin
|
41
|
-
fNumberOfFrames := 10;
|
42
|
-
fMaximumFrameScore := 10;
|
43
44
|
fRolls := TList<integer>.Create;
|
44
45
|
end;
|
45
46
|
|
@@ -52,29 +53,52 @@ function TBowlingGame.Score: integer;
|
|
52
53
|
var lFrameIndex: integer;
|
53
54
|
i: integer;
|
54
55
|
lScore: integer;
|
56
|
+
lStrikeBonus: integer;
|
57
|
+
lFrameScore: integer;
|
55
58
|
begin
|
56
59
|
lScore := 0;
|
57
60
|
lFrameIndex := 0;
|
58
|
-
|
59
|
-
|
60
|
-
if IsStrike(lFrameIndex) then
|
61
|
+
try
|
62
|
+
for i := 1 to fNumberOfFrames do
|
61
63
|
begin
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
64
|
+
if fRolls.Count <= lFrameIndex then
|
65
|
+
raise EArgumentException.Create('Not a proper game');
|
66
|
+
|
67
|
+
if IsStrike(lFrameIndex) then
|
68
|
+
begin
|
69
|
+
if (fRolls.Count <= lFrameIndex + 2) then
|
70
|
+
raise EArgumentException.Create('Not a proper game');
|
71
|
+
|
72
|
+
lStrikeBonus := StrikeBonus(lFrameIndex);
|
73
|
+
if (lStrikeBonus > fMaximumFrameScore) and not IsStrike(lFrameIndex + 1) then
|
74
|
+
raise EArgumentException.Create('Not a proper game');
|
75
|
+
|
76
|
+
lScore := lScore + 10 + lStrikeBonus;
|
77
|
+
inc(lFrameIndex, ifthen(i = fNumberOfFrames, 3, 1));
|
78
|
+
end
|
79
|
+
else
|
80
|
+
if IsSpare(lFrameIndex) then
|
81
|
+
begin
|
82
|
+
if (fRolls.Count <= lFrameIndex + 2) then
|
83
|
+
raise EArgumentException.Create('Not a proper game');
|
84
|
+
|
85
|
+
lScore := lScore + 10 + SpareBonus(lFrameIndex);
|
86
|
+
inc(lFrameIndex, ifthen(i = fNumberOfFrames, 3, 2));
|
87
|
+
end
|
88
|
+
else
|
89
|
+
begin
|
90
|
+
lFrameScore := SumOfPinsInFrame(lFrameIndex);
|
91
|
+
if (lFrameScore < 0) or (lFrameScore > 10) then
|
92
|
+
raise EArgumentException.Create('Not a proper game');
|
93
|
+
|
94
|
+
lScore := lScore + lFrameScore;
|
95
|
+
inc(lFrameIndex, 2);
|
96
|
+
end;
|
75
97
|
end;
|
98
|
+
result := ifthen(CorrectNumberOfRolls(lFrameIndex), lScore, -1);
|
99
|
+
except
|
100
|
+
result := -1;
|
76
101
|
end;
|
77
|
-
result := lScore;
|
78
102
|
end;
|
79
103
|
|
80
104
|
function TBowlingGame.IsStrike(aFrameIndex: Integer): Boolean;
|
@@ -102,4 +126,9 @@ begin
|
|
102
126
|
result := fRolls[aFrameIndex] + fRolls[aFrameIndex + 1];
|
103
127
|
end;
|
104
128
|
|
129
|
+
function TBowlingGame.CorrectNumberOfRolls(aFrameIndex: Integer): boolean;
|
130
|
+
begin
|
131
|
+
result := aFrameIndex = fRolls.Count;
|
132
|
+
end;
|
133
|
+
|
105
134
|
end.
|
@@ -10,90 +10,281 @@ type
|
|
10
10
|
[TestFixture]
|
11
11
|
BowlingTests = class(TObject)
|
12
12
|
private
|
13
|
-
class
|
14
|
-
class procedure RollSpare(game: IBowlingGame); static;
|
15
|
-
class procedure RollStrike(game: IBowlingGame); static;
|
13
|
+
class function RollMany(pins: array of integer; game: IBowlingGame): IBowlingGame; static;
|
16
14
|
public
|
17
15
|
[Test]
|
18
|
-
|
19
|
-
|
16
|
+
procedure Should_be_able_to_score_a_game_with_all_zeros;
|
17
|
+
|
18
|
+
[Test]
|
19
|
+
[Ignore('Comment this line to run this test')]
|
20
|
+
procedure Should_be_able_to_score_a_game_with_no_strikes_or_spares;
|
21
|
+
|
22
|
+
[Test]
|
23
|
+
[Ignore('Comment this line to run this test')]
|
24
|
+
procedure A_spare_followed_by_zeros_is_worth_ten_points;
|
25
|
+
|
26
|
+
[Test]
|
27
|
+
[Ignore('Comment this line to run this test')]
|
28
|
+
procedure Points_scored_in_the_roll_after_a_spare_are_counted_twice;
|
29
|
+
|
30
|
+
[Test]
|
31
|
+
[Ignore('Comment this line to run this test')]
|
32
|
+
procedure Consecutive_spares_each_get_a_one_roll_bonus;
|
33
|
+
|
34
|
+
[Test]
|
35
|
+
[Ignore('Comment this line to run this test')]
|
36
|
+
procedure A_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once;
|
37
|
+
|
38
|
+
[Test]
|
39
|
+
[Ignore('Comment this line to run this test')]
|
40
|
+
procedure A_strike_earns_ten_points_in_frame_with_a_single_roll;
|
41
|
+
|
42
|
+
[Test]
|
43
|
+
[Ignore('Comment this line to run this test')]
|
44
|
+
procedure Points_scored_in_the_two_rolls_after_a_strike_are_counted_twice_as_a_bonus;
|
45
|
+
|
46
|
+
[Test]
|
47
|
+
[Ignore('Comment this line to run this test')]
|
48
|
+
procedure Consecutive_strikes_each_get_the_two_roll_bonus;
|
49
|
+
|
50
|
+
[Test]
|
51
|
+
[Ignore('Comment this line to run this test')]
|
52
|
+
procedure A_strike_in_the_last_frame_gets_a_two_roll_bonus_that_is_counted_once;
|
53
|
+
|
54
|
+
[Test]
|
55
|
+
[Ignore('Comment this line to run this test')]
|
56
|
+
procedure Rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll;
|
57
|
+
|
58
|
+
[Test]
|
59
|
+
[Ignore('Comment this line to run this test')]
|
60
|
+
procedure Strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls;
|
61
|
+
|
62
|
+
[Test]
|
63
|
+
[Ignore('Comment this line to run this test')]
|
64
|
+
procedure A_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus;
|
65
|
+
|
66
|
+
[Test]
|
67
|
+
[Ignore('Comment this line to run this test')]
|
68
|
+
procedure All_strikes_is_a_perfect_game;
|
69
|
+
|
70
|
+
[Test]
|
71
|
+
[Ignore('Comment this line to run this test')]
|
72
|
+
procedure Rolls_can_not_score_negative_points;
|
73
|
+
|
74
|
+
[Test]
|
75
|
+
[Ignore('Comment this line to run this test')]
|
76
|
+
procedure A_roll_can_not_score_more_than_10_points;
|
77
|
+
|
78
|
+
[Test]
|
79
|
+
[Ignore('Comment this line to run this test')]
|
80
|
+
procedure Two_rolls_in_a_frame_can_not_score_more_than_10_points;
|
81
|
+
|
82
|
+
[Test]
|
83
|
+
[Ignore('Comment this line to run this test')]
|
84
|
+
procedure Two_bonus_rolls_after_a_strike_in_the_last_frame_can_not_score_more_than_10_points;
|
85
|
+
|
20
86
|
[Test]
|
21
|
-
[Ignore]
|
22
|
-
procedure
|
87
|
+
[Ignore('Comment this line to run this test')]
|
88
|
+
procedure An_unstarted_game_can_not_be_scored;
|
89
|
+
|
90
|
+
[Test]
|
91
|
+
[Ignore('Comment this line to run this test')]
|
92
|
+
procedure An_incomplete_game_can_not_be_scored;
|
93
|
+
|
23
94
|
[Test]
|
24
|
-
[Ignore]
|
25
|
-
procedure
|
95
|
+
[Ignore('Comment this line to run this test')]
|
96
|
+
procedure A_game_with_more_than_ten_frames_can_not_be_scored;
|
97
|
+
|
26
98
|
[Test]
|
27
|
-
[Ignore]
|
28
|
-
procedure
|
99
|
+
[Ignore('Comment this line to run this test')]
|
100
|
+
procedure Bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
|
101
|
+
|
102
|
+
[Test]
|
103
|
+
[Ignore('Comment this line to run this test')]
|
104
|
+
procedure Both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
|
105
|
+
|
29
106
|
[Test]
|
30
|
-
[Ignore]
|
31
|
-
procedure
|
107
|
+
[Ignore('Comment this line to run this test')]
|
108
|
+
procedure Bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
|
32
109
|
end;
|
33
110
|
|
34
111
|
implementation
|
112
|
+
uses System.SysUtils;
|
35
113
|
|
36
|
-
procedure BowlingTests.
|
114
|
+
procedure BowlingTests.Should_be_able_to_score_a_game_with_all_zeros;
|
37
115
|
var game: IBowlingGame;
|
38
116
|
begin
|
39
|
-
game := NewBowlingGame;
|
40
|
-
|
41
|
-
assert.AreEqual(0,game.Score);
|
117
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
118
|
+
assert.AreEqual(0, game.Score);
|
42
119
|
end;
|
43
120
|
|
44
|
-
procedure BowlingTests.
|
121
|
+
procedure BowlingTests.Should_be_able_to_score_a_game_with_no_strikes_or_spares;
|
45
122
|
var game: IBowlingGame;
|
46
123
|
begin
|
47
|
-
game := NewBowlingGame;
|
48
|
-
|
49
|
-
assert.AreEqual(20,game.Score);
|
124
|
+
game := RollMany([3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6], NewBowlingGame);
|
125
|
+
assert.AreEqual(90, game.Score);
|
50
126
|
end;
|
51
127
|
|
52
|
-
procedure BowlingTests.
|
128
|
+
procedure BowlingTests.A_spare_followed_by_zeros_is_worth_ten_points;
|
53
129
|
var game: IBowlingGame;
|
54
130
|
begin
|
55
|
-
game := NewBowlingGame;
|
56
|
-
|
57
|
-
|
58
|
-
|
131
|
+
game := RollMany([6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
132
|
+
assert.AreEqual(10, game.Score);
|
133
|
+
end;
|
134
|
+
|
135
|
+
procedure BowlingTests.Points_scored_in_the_roll_after_a_spare_are_counted_twice;
|
136
|
+
var game: IBowlingGame;
|
137
|
+
begin
|
138
|
+
game := RollMany([6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
59
139
|
assert.AreEqual(16, game.Score);
|
60
140
|
end;
|
61
141
|
|
62
|
-
procedure BowlingTests.
|
142
|
+
procedure BowlingTests.Consecutive_spares_each_get_a_one_roll_bonus;
|
143
|
+
var game: IBowlingGame;
|
144
|
+
begin
|
145
|
+
game := RollMany([5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
146
|
+
assert.AreEqual(31, game.Score);
|
147
|
+
end;
|
148
|
+
|
149
|
+
procedure BowlingTests.A_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once;
|
150
|
+
var game: IBowlingGame;
|
151
|
+
begin
|
152
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7], NewBowlingGame);
|
153
|
+
assert.AreEqual(17, game.Score);
|
154
|
+
end;
|
155
|
+
|
156
|
+
procedure BowlingTests.A_strike_earns_ten_points_in_frame_with_a_single_roll;
|
157
|
+
var game: IBowlingGame;
|
158
|
+
begin
|
159
|
+
game := RollMany([10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
160
|
+
assert.AreEqual(10, game.Score);
|
161
|
+
end;
|
162
|
+
|
163
|
+
procedure BowlingTests.Points_scored_in_the_two_rolls_after_a_strike_are_counted_twice_as_a_bonus;
|
164
|
+
var game: IBowlingGame;
|
165
|
+
begin
|
166
|
+
game := RollMany([10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
167
|
+
assert.AreEqual(26, game.Score);
|
168
|
+
end;
|
169
|
+
|
170
|
+
procedure BowlingTests.Consecutive_strikes_each_get_the_two_roll_bonus;
|
171
|
+
var game: IBowlingGame;
|
172
|
+
begin
|
173
|
+
game := RollMany([10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
174
|
+
assert.AreEqual(81, game.Score);
|
175
|
+
end;
|
176
|
+
|
177
|
+
procedure BowlingTests.A_strike_in_the_last_frame_gets_a_two_roll_bonus_that_is_counted_once;
|
178
|
+
var game: IBowlingGame;
|
179
|
+
begin
|
180
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1], NewBowlingGame);
|
181
|
+
assert.AreEqual(18, game.Score);
|
182
|
+
end;
|
183
|
+
|
184
|
+
procedure BowlingTests.Rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll;
|
185
|
+
var game: IBowlingGame;
|
186
|
+
begin
|
187
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3], NewBowlingGame);
|
188
|
+
assert.AreEqual(20, game.Score);
|
189
|
+
end;
|
190
|
+
|
191
|
+
procedure BowlingTests.Strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls;
|
192
|
+
var game: IBowlingGame;
|
193
|
+
begin
|
194
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10], NewBowlingGame);
|
195
|
+
assert.AreEqual(30, game.Score);
|
196
|
+
end;
|
197
|
+
|
198
|
+
procedure BowlingTests.A_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus;
|
199
|
+
var game: IBowlingGame;
|
200
|
+
begin
|
201
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10], NewBowlingGame);
|
202
|
+
assert.AreEqual(20, game.Score);
|
203
|
+
end;
|
204
|
+
|
205
|
+
procedure BowlingTests.All_strikes_is_a_perfect_game;
|
206
|
+
var game: IBowlingGame;
|
207
|
+
begin
|
208
|
+
game := RollMany([10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], NewBowlingGame);
|
209
|
+
assert.AreEqual(300, game.Score);
|
210
|
+
end;
|
211
|
+
|
212
|
+
procedure BowlingTests.Rolls_can_not_score_negative_points;
|
213
|
+
var game: IBowlingGame;
|
214
|
+
begin
|
215
|
+
game := RollMany([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
216
|
+
Assert.AreEqual(-1, game.Score);
|
217
|
+
end;
|
218
|
+
|
219
|
+
procedure BowlingTests.A_roll_can_not_score_more_than_10_points;
|
220
|
+
var game: IBowlingGame;
|
221
|
+
begin
|
222
|
+
game := RollMany([11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
223
|
+
Assert.AreEqual(-1, game.Score);
|
224
|
+
end;
|
225
|
+
|
226
|
+
procedure BowlingTests.Two_rolls_in_a_frame_can_not_score_more_than_10_points;
|
227
|
+
var game: IBowlingGame;
|
228
|
+
begin
|
229
|
+
game := RollMany([5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
230
|
+
Assert.AreEqual(-1, game.Score);
|
231
|
+
end;
|
232
|
+
|
233
|
+
procedure BowlingTests.Two_bonus_rolls_after_a_strike_in_the_last_frame_can_not_score_more_than_10_points;
|
63
234
|
var game: IBowlingGame;
|
64
235
|
begin
|
65
|
-
game := NewBowlingGame;
|
66
|
-
|
67
|
-
game.Roll(3);
|
68
|
-
game.Roll(4);
|
69
|
-
RollMany(0, 16, game);
|
70
|
-
assert.AreEqual(24, game.Score);
|
236
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6], NewBowlingGame);
|
237
|
+
Assert.AreEqual(-1, game.Score);
|
71
238
|
end;
|
72
239
|
|
73
|
-
procedure BowlingTests.
|
240
|
+
procedure BowlingTests.An_unstarted_game_can_not_be_scored;
|
74
241
|
var game: IBowlingGame;
|
75
242
|
begin
|
76
|
-
game := NewBowlingGame;
|
77
|
-
|
78
|
-
assert.AreEqual(300, Game.Score);
|
243
|
+
game := RollMany([],NewBowlingGame);
|
244
|
+
Assert.AreEqual(-1, game.Score);
|
79
245
|
end;
|
80
246
|
|
81
|
-
|
82
|
-
var
|
247
|
+
procedure BowlingTests.An_incomplete_game_can_not_be_scored;
|
248
|
+
var game: IBowlingGame;
|
249
|
+
begin
|
250
|
+
game := RollMany([0, 0], NewBowlingGame);
|
251
|
+
Assert.AreEqual(-1, game.Score);
|
252
|
+
end;
|
253
|
+
|
254
|
+
procedure BowlingTests.A_game_with_more_than_ten_frames_can_not_be_scored;
|
255
|
+
var game: IBowlingGame;
|
256
|
+
begin
|
257
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
|
258
|
+
Assert.AreEqual(-1, game.Score);
|
259
|
+
end;
|
260
|
+
|
261
|
+
procedure BowlingTests.Bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
|
262
|
+
var game: IBowlingGame;
|
83
263
|
begin
|
84
|
-
|
85
|
-
|
264
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10], NewBowlingGame);
|
265
|
+
Assert.AreEqual(-1, game.Score);
|
86
266
|
end;
|
87
267
|
|
88
|
-
|
268
|
+
procedure BowlingTests.Both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
|
269
|
+
var game: IBowlingGame;
|
270
|
+
begin
|
271
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10], NewBowlingGame);
|
272
|
+
Assert.AreEqual(-1, game.Score);
|
273
|
+
end;
|
274
|
+
|
275
|
+
procedure BowlingTests.Bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
|
276
|
+
var game: IBowlingGame;
|
89
277
|
begin
|
90
|
-
game
|
91
|
-
game.
|
278
|
+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3], NewBowlingGame);
|
279
|
+
Assert.AreEqual(-1, game.Score);
|
92
280
|
end;
|
93
281
|
|
94
|
-
class
|
282
|
+
class function BowlingTests.RollMany(pins: array of integer; game: IBowlingGame): IBowlingGame;
|
283
|
+
var count: integer;
|
95
284
|
begin
|
96
|
-
|
285
|
+
for count in pins do
|
286
|
+
game.Roll(count);
|
287
|
+
result := game;
|
97
288
|
end;
|
98
289
|
|
99
290
|
initialization
|
@@ -10,25 +10,25 @@ import (
|
|
10
10
|
|
11
11
|
type operatorFn func(stack *[]int) error
|
12
12
|
|
13
|
-
type
|
13
|
+
type operatorID byte
|
14
14
|
|
15
15
|
const (
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
opAdd operatorID = iota
|
17
|
+
opSub
|
18
|
+
opMul
|
19
|
+
opDiv
|
20
|
+
opDrop
|
21
|
+
opDup
|
22
|
+
opSwap
|
23
|
+
opOver
|
24
|
+
opConst
|
25
|
+
opUserDef
|
26
|
+
opEndDef
|
27
27
|
)
|
28
28
|
|
29
29
|
type operatorTyp struct {
|
30
30
|
fn operatorFn
|
31
|
-
id
|
31
|
+
id operatorID
|
32
32
|
}
|
33
33
|
|
34
34
|
func Forth(input []string) (result []int, err error) {
|
@@ -73,15 +73,15 @@ func parse(phrase string, userDefs map[string][]operatorTyp) (oplist []operatorT
|
|
73
73
|
if udef, ok := userDefs[w]; ok {
|
74
74
|
oplist = append(oplist, udef...)
|
75
75
|
} else if op, ok := builtinOps[w]; ok {
|
76
|
-
if op.id ==
|
76
|
+
if op.id == opUserDef {
|
77
77
|
// Handle user defined word definition.
|
78
78
|
t++
|
79
79
|
if t >= len(words)-2 {
|
80
|
-
return nil,
|
80
|
+
return nil, errEmptyUserDef
|
81
81
|
}
|
82
82
|
userword := strings.ToUpper(words[t])
|
83
83
|
if _, numerr := strconv.Atoi(userword); numerr == nil {
|
84
|
-
return nil,
|
84
|
+
return nil, errInvalidUserDef
|
85
85
|
}
|
86
86
|
t++
|
87
87
|
var userops []operatorTyp
|
@@ -90,17 +90,16 @@ func parse(phrase string, userDefs map[string][]operatorTyp) (oplist []operatorT
|
|
90
90
|
if err != nil {
|
91
91
|
return nil, err
|
92
92
|
}
|
93
|
-
if oneOp[0].id ==
|
93
|
+
if oneOp[0].id == opEndDef {
|
94
94
|
break
|
95
95
|
}
|
96
96
|
userops = append(userops, oneOp...)
|
97
97
|
t++
|
98
98
|
}
|
99
99
|
if len(userops) == 0 {
|
100
|
-
return nil,
|
101
|
-
} else {
|
102
|
-
userDefs[userword] = userops
|
100
|
+
return nil, errEmptyUserDef
|
103
101
|
}
|
102
|
+
userDefs[userword] = userops
|
104
103
|
} else {
|
105
104
|
// Normal builtin operator.
|
106
105
|
oplist = append(oplist, op)
|
@@ -113,7 +112,7 @@ func parse(phrase string, userDefs map[string][]operatorTyp) (oplist []operatorT
|
|
113
112
|
return nil, err
|
114
113
|
}
|
115
114
|
oplist = append(oplist,
|
116
|
-
operatorTyp{id:
|
115
|
+
operatorTyp{id: opConst,
|
117
116
|
fn: func(stack *[]int) error {
|
118
117
|
push(stack, x)
|
119
118
|
return nil
|
@@ -126,16 +125,16 @@ func parse(phrase string, userDefs map[string][]operatorTyp) (oplist []operatorT
|
|
126
125
|
|
127
126
|
// builtinOps are the pre-defined operators to support.
|
128
127
|
var builtinOps = map[string]operatorTyp{
|
129
|
-
"+": {add,
|
130
|
-
"-": {subtract,
|
131
|
-
"*": {multiply,
|
132
|
-
"/": {divide,
|
133
|
-
"DUP": {dup,
|
134
|
-
"DROP": {drop,
|
135
|
-
"SWAP": {swap,
|
136
|
-
"OVER": {over,
|
137
|
-
":": {nil,
|
138
|
-
";": {nil,
|
128
|
+
"+": {add, opAdd},
|
129
|
+
"-": {subtract, opSub},
|
130
|
+
"*": {multiply, opMul},
|
131
|
+
"/": {divide, opDiv},
|
132
|
+
"DUP": {dup, opDrop},
|
133
|
+
"DROP": {drop, opDup},
|
134
|
+
"SWAP": {swap, opSwap},
|
135
|
+
"OVER": {over, opOver},
|
136
|
+
":": {nil, opUserDef},
|
137
|
+
";": {nil, opEndDef},
|
139
138
|
}
|
140
139
|
|
141
140
|
func pop(stack *[]int) (v int, err error) {
|
@@ -145,7 +144,7 @@ func pop(stack *[]int) (v int, err error) {
|
|
145
144
|
*stack = (*stack)[:slen-1]
|
146
145
|
return v, nil
|
147
146
|
}
|
148
|
-
return 0,
|
147
|
+
return 0, errNotEnoughOperands
|
149
148
|
}
|
150
149
|
|
151
150
|
func pop2(stack *[]int) (v1, v2 int, err error) {
|
@@ -188,7 +187,7 @@ func divide(stack *[]int) error {
|
|
188
187
|
return err
|
189
188
|
}
|
190
189
|
if v1 == 0 {
|
191
|
-
return
|
190
|
+
return errDivideByZero
|
192
191
|
}
|
193
192
|
push(stack, v2/v1)
|
194
193
|
return nil
|
@@ -230,9 +229,9 @@ func swap(stack *[]int) error {
|
|
230
229
|
return nil
|
231
230
|
}
|
232
231
|
|
233
|
-
var
|
234
|
-
var
|
235
|
-
var
|
236
|
-
var
|
232
|
+
var errNotEnoughOperands = errors.New("not enough operands")
|
233
|
+
var errDivideByZero = errors.New("attempt to divide by zero")
|
234
|
+
var errEmptyUserDef = errors.New("empty user definition")
|
235
|
+
var errInvalidUserDef = errors.New("invalid user def word")
|
237
236
|
|
238
237
|
const testVersion = 1
|
@@ -140,7 +140,7 @@ func TestGarden(t *testing.T) {
|
|
140
140
|
t.Fatalf("Garden %d lookup %s returned ok = %t, want %t.",
|
141
141
|
test.number, l.child, ok, l.ok)
|
142
142
|
case ok && !reflect.DeepEqual(plants, l.plants):
|
143
|
-
t.Fatalf("Garden %d lookup %s = %
|
143
|
+
t.Fatalf("Garden %d lookup %s = %q, want %q.",
|
144
144
|
test.number, l.child, plants, l.plants)
|
145
145
|
}
|
146
146
|
}
|
@@ -192,7 +192,7 @@ RVGCCGCV`
|
|
192
192
|
t.Skip("Garden %d lookup %s returned ok = false, want true.",
|
193
193
|
n, child)
|
194
194
|
case !reflect.DeepEqual(plants, expPlants):
|
195
|
-
t.Fatalf("Garden %d lookup %s = %
|
195
|
+
t.Fatalf("Garden %d lookup %s = %q, want %q.",
|
196
196
|
n, child, plants, expPlants)
|
197
197
|
}
|
198
198
|
}
|
@@ -90,6 +90,8 @@ public class AllergiesTest {
|
|
90
90
|
Allergies allergies = new Allergies(5);
|
91
91
|
|
92
92
|
assertEquals(true, allergies.isAllergicTo(Allergen.EGGS));
|
93
|
+
assertEquals(true, allergies.isAllergicTo(Allergen.SHELLFISH));
|
94
|
+
assertEquals(false, allergies.isAllergicTo(Allergen.STRAWBERRIES));
|
93
95
|
}
|
94
96
|
|
95
97
|
@Ignore
|
data/tracks/scala/config.json
CHANGED
@@ -0,0 +1,95 @@
|
|
1
|
+
class Node[+T]
|
2
|
+
case object Empty extends Node[Nothing]
|
3
|
+
case class NonEmpty[T](value: T, next: Node[T]) extends Node[T]
|
4
|
+
|
5
|
+
trait SimpleLinkedList[T] {
|
6
|
+
def isEmpty: Boolean
|
7
|
+
def value: T
|
8
|
+
def add(item: T): SimpleLinkedList[T]
|
9
|
+
def next: SimpleLinkedList[T]
|
10
|
+
def reverse: SimpleLinkedList[T]
|
11
|
+
def toSeq: Seq[T]
|
12
|
+
}
|
13
|
+
|
14
|
+
class SimpleLinkedListImpl[T](first: Node[T]) extends SimpleLinkedList[T] {
|
15
|
+
|
16
|
+
def isEmpty: Boolean = first == Empty
|
17
|
+
|
18
|
+
def value: T = first match {
|
19
|
+
case Empty => throw new NoSuchElementException
|
20
|
+
case node: NonEmpty[T] => node.value
|
21
|
+
}
|
22
|
+
|
23
|
+
def add(item: T): SimpleLinkedList[T] = {
|
24
|
+
var reversed = reverse
|
25
|
+
var current = NonEmpty[T](item, Empty)
|
26
|
+
|
27
|
+
while (!reversed.isEmpty) {
|
28
|
+
val value = reversed.value
|
29
|
+
val newNode = NonEmpty[T](value, current)
|
30
|
+
|
31
|
+
current = newNode
|
32
|
+
reversed = reversed.next
|
33
|
+
}
|
34
|
+
|
35
|
+
new SimpleLinkedListImpl[T](current)
|
36
|
+
}
|
37
|
+
|
38
|
+
def next: SimpleLinkedList[T] = first match {
|
39
|
+
case Empty => this
|
40
|
+
case node: NonEmpty[T] => new SimpleLinkedListImpl[T](first.asInstanceOf[NonEmpty[T]].next)
|
41
|
+
}
|
42
|
+
|
43
|
+
def reverse: SimpleLinkedList[T] = {
|
44
|
+
var newLast: Node[T] = Empty
|
45
|
+
var prev: Node[T] = Empty
|
46
|
+
var current = first
|
47
|
+
var next: Node[T] = Empty
|
48
|
+
while (current != Empty) {
|
49
|
+
val newNode = NonEmpty[T](current.asInstanceOf[NonEmpty[T]].value, prev)
|
50
|
+
|
51
|
+
if (newLast == Empty) {
|
52
|
+
newLast = newNode
|
53
|
+
}
|
54
|
+
|
55
|
+
next = current.asInstanceOf[NonEmpty[T]].next
|
56
|
+
prev = newNode
|
57
|
+
current = next
|
58
|
+
}
|
59
|
+
|
60
|
+
new SimpleLinkedListImpl[T](prev)
|
61
|
+
}
|
62
|
+
|
63
|
+
def length: Int = {
|
64
|
+
var len = 0
|
65
|
+
|
66
|
+
var current = first
|
67
|
+
while (current != Empty) {
|
68
|
+
len = len + 1
|
69
|
+
current = current.asInstanceOf[NonEmpty[T]].next
|
70
|
+
}
|
71
|
+
|
72
|
+
len
|
73
|
+
}
|
74
|
+
|
75
|
+
def toSeq: Seq[T] = {
|
76
|
+
var xs = List[T]()
|
77
|
+
|
78
|
+
var current = first
|
79
|
+
while (current != Empty) {
|
80
|
+
xs = current.asInstanceOf[NonEmpty[T]].value :: xs
|
81
|
+
current = current.asInstanceOf[NonEmpty[T]].next
|
82
|
+
}
|
83
|
+
|
84
|
+
xs.reverse
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
object SimpleLinkedList {
|
89
|
+
def apply[T](): SimpleLinkedList[T] = new SimpleLinkedListImpl[T](Empty)
|
90
|
+
|
91
|
+
def apply[T](ts: T*): SimpleLinkedList[T] = fromSeq(ts)
|
92
|
+
|
93
|
+
def fromSeq[T](seq: Seq[T]): SimpleLinkedList[T] =
|
94
|
+
seq.foldLeft(SimpleLinkedList[T]())((acc, t) => acc.add(t))
|
95
|
+
}
|
@@ -0,0 +1,108 @@
|
|
1
|
+
import org.scalacheck.{Arbitrary}
|
2
|
+
import org.scalatest.prop.GeneratorDrivenPropertyChecks
|
3
|
+
import org.scalatest.{FlatSpec, Matchers}
|
4
|
+
|
5
|
+
|
6
|
+
class SimpleLinkedListTest extends FlatSpec with Matchers with GeneratorDrivenPropertyChecks {
|
7
|
+
|
8
|
+
private implicit def arbitrarySimpleLinkedList[T](implicit arbitraryTs: Arbitrary[Array[T]]): Arbitrary[SimpleLinkedList[T]] =
|
9
|
+
Arbitrary {
|
10
|
+
arbitraryTs.arbitrary map (SimpleLinkedList(_:_*))
|
11
|
+
}
|
12
|
+
|
13
|
+
it should "handle single item list" in {
|
14
|
+
val list = SimpleLinkedList().add(1)
|
15
|
+
list.isEmpty should be (false)
|
16
|
+
list.value should be (1)
|
17
|
+
}
|
18
|
+
|
19
|
+
it should "handle single item has no next item" in {
|
20
|
+
pending
|
21
|
+
val list = SimpleLinkedList().add(1)
|
22
|
+
list.next.isEmpty should be (true)
|
23
|
+
}
|
24
|
+
|
25
|
+
it should "handle two item list" in {
|
26
|
+
pending
|
27
|
+
val list = SimpleLinkedList().add(1).add(2)
|
28
|
+
list.value should be (1)
|
29
|
+
list.next.value should be (2)
|
30
|
+
}
|
31
|
+
|
32
|
+
it should "handle two item list has no next value" in {
|
33
|
+
pending
|
34
|
+
val list = SimpleLinkedList().add(1).add(2)
|
35
|
+
list.next.next.isEmpty should be (true)
|
36
|
+
}
|
37
|
+
|
38
|
+
it should "allow creation from a Seq" in {
|
39
|
+
pending
|
40
|
+
val list = SimpleLinkedList.fromSeq(List(3, 2, 1))
|
41
|
+
list.value should be (3)
|
42
|
+
list.next.value should be (2)
|
43
|
+
list.next.next.value should be (1)
|
44
|
+
}
|
45
|
+
|
46
|
+
it should "allow conversion to a Seq" in {
|
47
|
+
pending
|
48
|
+
val list = SimpleLinkedList.fromSeq(List(3, 2, 1))
|
49
|
+
val seq = list.toSeq
|
50
|
+
seq should be (List(3, 2, 1))
|
51
|
+
}
|
52
|
+
|
53
|
+
it should "handle reverse" in {
|
54
|
+
pending
|
55
|
+
val list = SimpleLinkedList.fromSeq(List(1, 2, 3, 4, 5, 6))
|
56
|
+
val reversed = list.reverse
|
57
|
+
reversed.value should be (6)
|
58
|
+
reversed.next.value should be (5)
|
59
|
+
reversed.next.next.value should be (4)
|
60
|
+
reversed.next.next.next.value should be (3)
|
61
|
+
reversed.next.next.next.next.value should be (2)
|
62
|
+
reversed.next.next.next.next.next.value should be (1)
|
63
|
+
}
|
64
|
+
|
65
|
+
it should "handle arbitrary list fromSeq toSeq" in {
|
66
|
+
pending
|
67
|
+
forAll { seq: Seq[Int] =>
|
68
|
+
assert(SimpleLinkedList.fromSeq(seq).toSeq == seq)
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
it should "handle reverse arbitrary list " in {
|
73
|
+
pending
|
74
|
+
forAll { seq: Seq[Int] =>
|
75
|
+
assert(SimpleLinkedList.fromSeq(seq).reverse.toSeq == seq.reverse)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
it should "reverse arbitrary list back to original" in {
|
80
|
+
pending
|
81
|
+
forAll { list: SimpleLinkedList[Int] =>
|
82
|
+
assert(list.reverse.reverse.toSeq == list.toSeq)
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
it should "return correct arbitrary value at index" in {
|
87
|
+
pending
|
88
|
+
def nthDatum(list: SimpleLinkedList[Int], i: Int): Int = {
|
89
|
+
(0 until i).foldLeft(list)((acc, j) => acc.next).value
|
90
|
+
}
|
91
|
+
|
92
|
+
forAll { xs: Seq[Int] =>
|
93
|
+
whenever(xs.nonEmpty) {
|
94
|
+
val list = SimpleLinkedList.fromSeq(xs)
|
95
|
+
xs.indices.foreach {
|
96
|
+
i => assert(nthDatum(list, i) == xs(i))
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
it should "handle arbitrary generics" in {
|
103
|
+
pending
|
104
|
+
forAll { xs: Seq[String] =>
|
105
|
+
assert(SimpleLinkedList.fromSeq(xs).toSeq == xs)
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trackler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.8.
|
4
|
+
version: 2.0.8.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katrina Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -7391,6 +7391,10 @@ files:
|
|
7391
7391
|
- tracks/scala/exercises/simple-cipher/example.scala
|
7392
7392
|
- tracks/scala/exercises/simple-cipher/src/main/scala/.keep
|
7393
7393
|
- tracks/scala/exercises/simple-cipher/src/test/scala/CipherTest.scala
|
7394
|
+
- tracks/scala/exercises/simple-linked-list/build.sbt
|
7395
|
+
- tracks/scala/exercises/simple-linked-list/example.scala
|
7396
|
+
- tracks/scala/exercises/simple-linked-list/src/main/scala/SimpleLinkedList.scala
|
7397
|
+
- tracks/scala/exercises/simple-linked-list/src/test/scala/SimpleLinkedListTest.scala
|
7394
7398
|
- tracks/scala/exercises/space-age/build.sbt
|
7395
7399
|
- tracks/scala/exercises/space-age/example.scala
|
7396
7400
|
- tracks/scala/exercises/space-age/src/main/scala/.keep
|