trackler 2.0.0.3 → 2.0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/CONTRIBUTING.md +1 -1
- data/common/README.md +4 -4
- data/common/exercises/bowling/canonical-data.json +8 -0
- data/common/exercises/hello-world/description.md +1 -1
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/.gitignore +1 -0
- data/tracks/c/bin/run-tests +3 -0
- data/tracks/c/config.json +9 -0
- data/tracks/c/exercises/clock/makefile +16 -0
- data/tracks/c/exercises/clock/src/clock.h +11 -0
- data/tracks/c/exercises/clock/src/example.c +31 -0
- data/tracks/c/exercises/clock/test/test_clock.c +489 -0
- data/tracks/c/exercises/clock/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/clock/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/clock/test/vendor/unity_internals.h +701 -0
- data/tracks/coldfusion/config.json +2 -1
- data/tracks/coldfusion/img/icon.png +0 -0
- data/tracks/crystal/Makefile +11 -15
- data/tracks/crystal/SETUP.md +1 -1
- data/tracks/crystal/docs/LEARNING.md +5 -3
- data/tracks/crystal/docs/TESTS.md +24 -3
- data/tracks/crystal/exercises/anagram/{anagram_spec.cr → spec/anagram_spec.cr} +1 -1
- data/tracks/crystal/exercises/anagram/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/atbash-cipher/{atbash_cipher_spec.cr → spec/atbash_cipher_spec.cr} +1 -1
- data/tracks/crystal/exercises/atbash-cipher/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/bob/{bob_spec.cr → spec/bob_spec.cr} +1 -1
- data/tracks/crystal/exercises/bob/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/bracket-push/{bracket_push_spec.cr → spec/bracket_push_spec.cr} +1 -1
- data/tracks/crystal/exercises/bracket-push/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/gigasecond/{gigasecond_spec.cr → spec/gigasecond_spec.cr} +1 -1
- data/tracks/crystal/exercises/gigasecond/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/hamming/{hamming_spec.cr → spec/hamming_spec.cr} +1 -1
- data/tracks/crystal/exercises/hamming/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/hello-world/HINTS.md +32 -0
- data/tracks/crystal/exercises/hello-world/{hello_world_spec.cr → spec/hello_world_spec.cr} +1 -1
- data/tracks/crystal/exercises/hello-world/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/largest-series-product/{largest_series_product_spec.cr → spec/largest_series_product_spec.cr} +1 -1
- data/tracks/crystal/exercises/largest-series-product/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/leap/{leap_spec.cr → spec/leap_spec.cr} +1 -1
- data/tracks/crystal/exercises/leap/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/pangram/{pangram_spec.cr → spec/pangram_spec.cr} +1 -1
- data/tracks/crystal/exercises/pangram/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/raindrops/{raindrops_spec.cr → spec/raindrops_spec.cr} +1 -1
- data/tracks/crystal/exercises/raindrops/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/react/{react_spec.cr → spec/react_spec.cr} +1 -1
- data/tracks/crystal/exercises/react/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/rna-transcription/{rna_transcription_spec.cr → spec/rna_transcription_spec.cr} +1 -1
- data/tracks/crystal/exercises/rna-transcription/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/roman-numerals/{roman_numerals_spec.cr → spec/roman_numerals_spec.cr} +1 -1
- data/tracks/crystal/exercises/roman-numerals/{example.cr → src/example.cr} +0 -0
- data/tracks/crystal/exercises/sieve/{sieve_spec.cr → spec/sieve_spec.cr} +1 -1
- data/tracks/crystal/exercises/sieve/{example.cr → src/example.cr} +0 -0
- data/tracks/haskell/.travis.yml +4 -2
- data/tracks/haskell/config.json +6 -6
- data/tracks/haskell/exercises/alphametics/package.yaml +0 -1
- data/tracks/haskell/exercises/atbash-cipher/package.yaml +0 -1
- data/tracks/haskell/exercises/bank-account/package.yaml +0 -1
- data/tracks/haskell/exercises/binary-search-tree/HINTS.md +3 -2
- data/tracks/haskell/exercises/binary-search-tree/src/BST.hs +2 -0
- data/tracks/haskell/exercises/change/test/Tests.hs +2 -1
- data/tracks/haskell/exercises/connect/package.yaml +0 -1
- data/tracks/haskell/exercises/crypto-square/package.yaml +0 -1
- data/tracks/haskell/exercises/custom-set/HINTS.md +3 -2
- data/tracks/haskell/exercises/custom-set/src/CustomSet.hs +3 -2
- data/tracks/haskell/exercises/food-chain/package.yaml +0 -1
- data/tracks/haskell/exercises/forth/HINTS.md +3 -2
- data/tracks/haskell/exercises/forth/src/Forth.hs +2 -0
- data/tracks/haskell/exercises/go-counting/package.yaml +0 -1
- data/tracks/haskell/exercises/grade-school/package.yaml +0 -1
- data/tracks/haskell/exercises/grains/src/Grains.hs +3 -1
- data/tracks/haskell/exercises/kindergarten-garden/package.yaml +0 -1
- data/tracks/haskell/exercises/largest-series-product/package.yaml +0 -1
- data/tracks/haskell/exercises/lens-person/package.yaml +0 -1
- data/tracks/haskell/exercises/linked-list/package.yaml +0 -1
- data/tracks/haskell/exercises/ocr-numbers/package.yaml +0 -2
- data/tracks/haskell/exercises/parallel-letter-frequency/package.yaml +0 -1
- data/tracks/haskell/exercises/rna-transcription/package.yaml +0 -1
- data/tracks/haskell/exercises/robot-name/package.yaml +0 -1
- data/tracks/haskell/exercises/saddle-points/package.yaml +0 -1
- data/tracks/haskell/exercises/say/package.yaml +0 -1
- data/tracks/haskell/exercises/scrabble-score/package.yaml +0 -1
- data/tracks/haskell/exercises/series/HINTS.md +23 -0
- data/tracks/haskell/exercises/series/examples/success-byteseqs/package.yaml +19 -0
- data/tracks/haskell/exercises/series/examples/success-byteseqs/src/Series.hs +26 -0
- data/tracks/haskell/exercises/series/src/Series.hs +2 -1
- data/tracks/haskell/exercises/series/test/Tests.hs +16 -11
- data/tracks/haskell/exercises/sgf-parsing/package.yaml +0 -1
- data/tracks/haskell/exercises/sieve/package.yaml +0 -1
- data/tracks/haskell/exercises/simple-cipher/package.yaml +0 -1
- data/tracks/haskell/exercises/triangle/package.yaml +0 -1
- data/tracks/haskell/exercises/word-count/examples/success-newtype/src/WordCount.hs +7 -4
- data/tracks/haskell/exercises/word-count/examples/success-simple/src/WordCount.hs +6 -2
- data/tracks/haskell/exercises/word-count/test/Tests.hs +30 -1
- data/tracks/haskell/exercises/wordy/package.yaml +0 -2
- data/tracks/java/docs/INSTALLATION.md +2 -0
- data/tracks/java/exercises/_template/build.gradle +1 -1
- data/tracks/java/exercises/accumulate/build.gradle +1 -1
- data/tracks/java/exercises/acronym/build.gradle +1 -1
- data/tracks/java/exercises/allergies/build.gradle +1 -1
- data/tracks/java/exercises/anagram/build.gradle +1 -1
- data/tracks/java/exercises/atbash-cipher/build.gradle +1 -1
- data/tracks/java/exercises/beer-song/build.gradle +1 -1
- data/tracks/java/exercises/binary/build.gradle +1 -1
- data/tracks/java/exercises/bob/build.gradle +1 -1
- data/tracks/java/exercises/crypto-square/build.gradle +1 -1
- data/tracks/java/exercises/etl/build.gradle +1 -1
- data/tracks/java/exercises/gigasecond/build.gradle +1 -1
- data/tracks/java/exercises/grade-school/build.gradle +1 -1
- data/tracks/java/exercises/hamming/build.gradle +1 -1
- data/tracks/java/exercises/hello-world/build.gradle +1 -1
- data/tracks/java/exercises/hexadecimal/build.gradle +1 -1
- data/tracks/java/exercises/linked-list/build.gradle +1 -1
- data/tracks/java/exercises/luhn/build.gradle +1 -1
- data/tracks/java/exercises/meetup/build.gradle +1 -1
- data/tracks/java/exercises/nth-prime/build.gradle +1 -1
- data/tracks/java/exercises/nucleotide-count/build.gradle +1 -1
- data/tracks/java/exercises/octal/build.gradle +1 -1
- data/tracks/java/exercises/pangram/build.gradle +1 -1
- data/tracks/java/exercises/pascals-triangle/build.gradle +1 -1
- data/tracks/java/exercises/phone-number/build.gradle +1 -1
- data/tracks/java/exercises/pig-latin/build.gradle +1 -1
- data/tracks/java/exercises/raindrops/build.gradle +1 -1
- data/tracks/java/exercises/rna-transcription/build.gradle +1 -1
- data/tracks/java/exercises/robot-name/build.gradle +1 -1
- data/tracks/java/exercises/roman-numerals/build.gradle +1 -1
- data/tracks/java/exercises/scrabble-score/build.gradle +1 -1
- data/tracks/java/exercises/sieve/build.gradle +1 -1
- data/tracks/java/exercises/simple-cipher/build.gradle +1 -1
- data/tracks/java/exercises/simple-linked-list/build.gradle +1 -1
- data/tracks/java/exercises/space-age/build.gradle +1 -1
- data/tracks/java/exercises/strain/build.gradle +1 -1
- data/tracks/java/exercises/triangle/build.gradle +1 -1
- data/tracks/java/exercises/trinary/build.gradle +1 -1
- data/tracks/java/exercises/word-count/build.gradle +1 -1
- data/tracks/ocaml/.travis-ci.sh +1 -1
- data/tracks/ocaml/.travis.yml +1 -1
- data/tracks/ocaml/README.md +1 -1
- data/tracks/ocaml/exercises/hamming/hamming.mli +1 -3
- data/tracks/ruby/exercises/leap/.version +1 -1
- data/tracks/ruby/exercises/leap/example.tt +3 -3
- data/tracks/ruby/exercises/leap/leap_test.rb +3 -4
- data/tracks/ruby/lib/leap_cases.rb +2 -2
- data/tracks/rust/exercises/bowling/tests/bowling.rs +29 -0
- data/tracks/swift/.gitignore +1 -0
- data/tracks/swift/.swift-version +1 -0
- data/tracks/swift/exercises/bowling/BowlingExample.swift +2 -2
- data/tracks/swift/exercises/bowling/BowlingTest.swift +84 -94
- data/tracks/swift/exercises/palindrome-products/PalindromeProductsExample.swift +19 -16
- data/tracks/tcl/README.md +3 -0
- data/tracks/tcl/config.json +2 -1
- data/tracks/tcl/img/icon.png +0 -0
- metadata +46 -33
- data/tracks/crystal/exercises/hello-world/GETTING_STARTED.md +0 -10
data/tracks/ocaml/.travis-ci.sh
CHANGED
data/tracks/ocaml/.travis.yml
CHANGED
data/tracks/ocaml/README.md
CHANGED
@@ -11,7 +11,7 @@ notes contain a few details specific to Ocaml.
|
|
11
11
|
|
12
12
|
## Prerequisites
|
13
13
|
|
14
|
-
The OCaml track assumes installation of OCaml version 4.
|
14
|
+
The OCaml track assumes installation of OCaml version 4.04.0, and installation of Core, OUnit, and React (for the Hangman exercise).
|
15
15
|
Assuming you have opam, these can be installed with
|
16
16
|
```bash
|
17
17
|
opam install core ounit react
|
@@ -1 +1 @@
|
|
1
|
-
2
|
1
|
+
2
|
@@ -7,7 +7,7 @@ require_relative 'leap'
|
|
7
7
|
# <%= sha1 %>
|
8
8
|
class Date
|
9
9
|
def leap?
|
10
|
-
|
10
|
+
raise RuntimeError, "Implement this yourself instead of using Ruby's implementation."
|
11
11
|
end
|
12
12
|
|
13
13
|
alias gregorian_leap? leap?
|
@@ -15,8 +15,8 @@ class Date
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class YearTest < Minitest::Test<% test_cases.each do |test_case| %>
|
18
|
-
def <%= test_case.name
|
19
|
-
skip
|
18
|
+
def <%= test_case.name %>
|
19
|
+
<%= test_case.skip %><% if test_case.expected%>
|
20
20
|
assert <%= test_case.do %>, "<%= test_case.failure_message%>"<% else %>
|
21
21
|
refute <%= test_case.do %>, "<%= test_case.failure_message%>"<% end%>
|
22
22
|
end
|
@@ -4,10 +4,10 @@ require 'minitest/autorun'
|
|
4
4
|
require_relative 'leap'
|
5
5
|
|
6
6
|
# Test data version:
|
7
|
-
#
|
7
|
+
# 7b0949e
|
8
8
|
class Date
|
9
9
|
def leap?
|
10
|
-
|
10
|
+
raise RuntimeError, "Implement this yourself instead of using Ruby's implementation."
|
11
11
|
end
|
12
12
|
|
13
13
|
alias gregorian_leap? leap?
|
@@ -16,6 +16,7 @@ end
|
|
16
16
|
|
17
17
|
class YearTest < Minitest::Test
|
18
18
|
def test_leap_year
|
19
|
+
# skip
|
19
20
|
assert Year.leap?(1996), "Expected 'true', 1996 is a leap year."
|
20
21
|
end
|
21
22
|
|
@@ -48,7 +49,6 @@ class YearTest < Minitest::Test
|
|
48
49
|
skip
|
49
50
|
assert Year.leap?(2000), "Expected 'true', 2000 is a leap year."
|
50
51
|
end
|
51
|
-
|
52
52
|
# Problems in exercism evolve over time, as we find better ways to ask
|
53
53
|
# questions.
|
54
54
|
# The version number refers to the version of the problem you solved,
|
@@ -65,7 +65,6 @@ class YearTest < Minitest::Test
|
|
65
65
|
#
|
66
66
|
# If you are curious, read more about constants on RubyDoc:
|
67
67
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
68
|
-
|
69
68
|
def test_bookkeeping
|
70
69
|
skip
|
71
70
|
assert_equal 2, BookKeeping::VERSION
|
@@ -286,6 +286,20 @@ fn you_can_not_roll_more_than_ten_pins_in_a_single_frame() {
|
|
286
286
|
assert!(game.roll(6).is_err());
|
287
287
|
}
|
288
288
|
|
289
|
+
#[test]
|
290
|
+
#[ignore]
|
291
|
+
fn first_bonus_ball_after_a_final_strike_can_not_score_an_invalid_number_of_pins() {
|
292
|
+
let mut game = BowlingGame::new();
|
293
|
+
|
294
|
+
for _ in 0..18 {
|
295
|
+
let _ = game.roll(0);
|
296
|
+
}
|
297
|
+
|
298
|
+
let _ = game.roll(10);
|
299
|
+
|
300
|
+
assert!(game.roll(11).is_err());
|
301
|
+
}
|
302
|
+
|
289
303
|
#[test]
|
290
304
|
#[ignore]
|
291
305
|
fn the_two_balls_after_a_final_strike_can_not_score_an_invalid_number_of_pins() {
|
@@ -331,6 +345,21 @@ fn the_two_balls_after_a_final_strike_can_not_be_a_non_strike_followed_by_a_stri
|
|
331
345
|
assert!(game.roll(10).is_err());
|
332
346
|
}
|
333
347
|
|
348
|
+
#[test]
|
349
|
+
#[ignore]
|
350
|
+
fn second_bonus_ball_after_a_final_strike_can_not_score_an_invalid_number_of_pins_even_if_first_is_strike() {
|
351
|
+
let mut game = BowlingGame::new();
|
352
|
+
|
353
|
+
for _ in 0..18 {
|
354
|
+
let _ = game.roll(0);
|
355
|
+
}
|
356
|
+
|
357
|
+
let _ = game.roll(10);
|
358
|
+
|
359
|
+
assert!(game.roll(10).is_ok());
|
360
|
+
assert!(game.roll(11).is_err());
|
361
|
+
}
|
362
|
+
|
334
363
|
#[test]
|
335
364
|
#[ignore]
|
336
365
|
fn if_the_last_frame_is_a_strike_you_can_not_score_before_the_extra_rolls_are_taken() {
|
data/tracks/swift/.gitignore
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
3.0
|
@@ -78,7 +78,7 @@ struct Bowling {
|
|
78
78
|
if isLastFrame {
|
79
79
|
let lastRollWasStrike = scoreCard[currentFrame]?.last == 10
|
80
80
|
|
81
|
-
if lastRollWasStrike {
|
81
|
+
if lastRollWasStrike || isSpare() {
|
82
82
|
return true
|
83
83
|
}
|
84
84
|
}
|
@@ -94,7 +94,7 @@ struct Bowling {
|
|
94
94
|
|
95
95
|
private func frameComplete() -> Bool {
|
96
96
|
if isLastFrame {
|
97
|
-
return
|
97
|
+
return isOpenFrame() && frameFilled() || frameFilled(rolls: 3)
|
98
98
|
}
|
99
99
|
|
100
100
|
return frameFilled() || isStrike()
|
@@ -2,7 +2,6 @@
|
|
2
2
|
import XCTest
|
3
3
|
#endif
|
4
4
|
|
5
|
-
// swiftlint:disable force_try
|
6
5
|
class BowlingTest: XCTestCase {
|
7
6
|
|
8
7
|
var game: Bowling!
|
@@ -11,170 +10,161 @@ class BowlingTest: XCTestCase {
|
|
11
10
|
game = Bowling()
|
12
11
|
}
|
13
12
|
|
14
|
-
func
|
15
|
-
|
16
|
-
|
17
|
-
rollNTimes(rolls: 18, pins: 0)
|
18
|
-
XCTAssertEqual(try? game.score(), 7)
|
19
|
-
}
|
20
|
-
|
21
|
-
func testMultipleFrames() {
|
22
|
-
[3, 4, 2, 3, 5, 2].forEach {
|
23
|
-
try? game.roll(pins: $0)
|
13
|
+
func roll(_ seriesOfPins: [Int]) throws {
|
14
|
+
for pins in seriesOfPins {
|
15
|
+
try game.roll(pins: pins)
|
24
16
|
}
|
25
|
-
rollNTimes(rolls: 14, pins: 0)
|
26
|
-
XCTAssertEqual(try? game.score(), 19)
|
27
17
|
}
|
28
18
|
|
29
|
-
func
|
30
|
-
|
19
|
+
func testAllZeros() {
|
20
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
21
|
+
|
31
22
|
XCTAssertEqual(try? game.score(), 0)
|
32
23
|
}
|
33
24
|
|
34
|
-
func
|
35
|
-
|
36
|
-
XCTAssertEqual(try? game.score(), 20)
|
37
|
-
}
|
25
|
+
func testNoStrikesOrSpares() {
|
26
|
+
try? roll([3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6])
|
38
27
|
|
39
|
-
func testAllOpenFrames() {
|
40
|
-
rollNTimes(rolls: 10, pins: 3, 6)
|
41
28
|
XCTAssertEqual(try? game.score(), 90)
|
42
29
|
}
|
43
30
|
|
44
|
-
func
|
45
|
-
try?
|
46
|
-
try? game.roll(pins: 5)
|
47
|
-
try? game.roll(pins: 3)
|
48
|
-
rollNTimes(rolls: 16, pins: 0)
|
31
|
+
func testSpareFollowedByZeros() {
|
32
|
+
try? roll([6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
49
33
|
|
50
|
-
XCTAssertEqual(try? game.score(),
|
34
|
+
XCTAssertEqual(try? game.score(), 10)
|
51
35
|
}
|
52
36
|
|
53
|
-
func
|
54
|
-
try?
|
55
|
-
try? game.roll(pins: 5)
|
56
|
-
try? game.roll(pins: 3)
|
57
|
-
try? game.roll(pins: 4)
|
58
|
-
rollNTimes(rolls: 16, pins: 0)
|
37
|
+
func testPointsScoredInRollAfterSpare() {
|
38
|
+
try? roll([6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
59
39
|
|
60
|
-
XCTAssertEqual(try? game.score(),
|
40
|
+
XCTAssertEqual(try? game.score(), 16)
|
61
41
|
}
|
62
42
|
|
63
|
-
func
|
64
|
-
try?
|
65
|
-
try? game.roll(pins: 10)
|
66
|
-
try? game.roll(pins: 10)
|
67
|
-
try? game.roll(pins: 5)
|
68
|
-
try? game.roll(pins: 3)
|
69
|
-
rollNTimes(rolls: 12, pins: 0)
|
43
|
+
func testConsecutiveSpares() {
|
44
|
+
try? roll([5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
70
45
|
|
71
|
-
XCTAssertEqual(try? game.score(),
|
46
|
+
XCTAssertEqual(try? game.score(), 31)
|
47
|
+
}
|
48
|
+
|
49
|
+
func testSpareInLastFrame() {
|
50
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7])
|
51
|
+
|
52
|
+
XCTAssertEqual(try? game.score(), 17)
|
53
|
+
}
|
54
|
+
|
55
|
+
func testStrikeWithSingleRoll() {
|
56
|
+
try? roll([10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
57
|
+
|
58
|
+
XCTAssertEqual(try? game.score(), 10)
|
59
|
+
}
|
60
|
+
|
61
|
+
func testTwoRollsAfterAStrike() {
|
62
|
+
try? roll([10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
63
|
+
|
64
|
+
XCTAssertEqual(try? game.score(), 26)
|
72
65
|
}
|
73
66
|
|
74
|
-
func
|
75
|
-
try?
|
76
|
-
try? game.roll(pins: 5)
|
77
|
-
try? game.roll(pins: 3)
|
78
|
-
try? game.roll(pins: 7)
|
79
|
-
try? game.roll(pins: 4)
|
80
|
-
try? game.roll(pins: 1)
|
81
|
-
rollNTimes(rolls: 14, pins: 0)
|
67
|
+
func testConsecutiveStrikes() {
|
68
|
+
try? roll([10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
82
69
|
|
83
|
-
XCTAssertEqual(try? game.score(),
|
70
|
+
XCTAssertEqual(try? game.score(), 81)
|
84
71
|
}
|
85
72
|
|
86
|
-
func
|
87
|
-
|
88
|
-
try? game.roll(pins: 10)
|
89
|
-
try? game.roll(pins: 7)
|
90
|
-
try? game.roll(pins: 1)
|
73
|
+
func testStrikeInLastFrame() {
|
74
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1])
|
91
75
|
|
92
76
|
XCTAssertEqual(try? game.score(), 18)
|
93
77
|
}
|
94
78
|
|
95
|
-
func
|
96
|
-
|
97
|
-
try? game.roll(pins: 9)
|
98
|
-
try? game.roll(pins: 1)
|
99
|
-
try? game.roll(pins: 7)
|
79
|
+
func testSpareWithTwoRollBonus() {
|
80
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3])
|
100
81
|
|
101
|
-
XCTAssertEqual(try? game.score(),
|
82
|
+
XCTAssertEqual(try? game.score(), 20)
|
102
83
|
}
|
103
84
|
|
104
|
-
func
|
105
|
-
|
106
|
-
try? game.roll(pins: 10)
|
107
|
-
try? game.roll(pins: 10)
|
108
|
-
try? game.roll(pins: 10)
|
85
|
+
func testStrikesWithTwoRollBonus() {
|
86
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10])
|
109
87
|
|
110
88
|
XCTAssertEqual(try? game.score(), 30)
|
111
89
|
}
|
112
90
|
|
113
|
-
func
|
114
|
-
|
91
|
+
func testStrikeAfterSpareInLastFrame() {
|
92
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10])
|
93
|
+
|
94
|
+
XCTAssertEqual(try? game.score(), 20)
|
95
|
+
}
|
96
|
+
|
97
|
+
func testAllStrikes() {
|
98
|
+
try? roll([10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10])
|
99
|
+
|
115
100
|
XCTAssertEqual(try? game.score(), 300)
|
116
101
|
}
|
117
102
|
|
118
|
-
func
|
119
|
-
XCTAssertThrowsError(try
|
103
|
+
func testNegativePoints() {
|
104
|
+
XCTAssertThrowsError(try roll([-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) { error in
|
120
105
|
XCTAssertEqual(error as? Bowling.BowlingError, .invalidNumberOfPins)
|
121
106
|
}
|
122
107
|
}
|
123
108
|
|
124
|
-
func
|
125
|
-
XCTAssertThrowsError(try
|
109
|
+
func testNoMoreThan10PinsPerRoll() {
|
110
|
+
XCTAssertThrowsError(try roll([11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) { error in
|
126
111
|
XCTAssertEqual(error as? Bowling.BowlingError, .invalidNumberOfPins)
|
127
112
|
}
|
128
113
|
}
|
129
114
|
|
130
|
-
func
|
131
|
-
try
|
132
|
-
XCTAssertThrowsError(try game.roll(pins: 6)) { error in
|
115
|
+
func testTwoRollsGreaterThan10() {
|
116
|
+
XCTAssertThrowsError(try roll([5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) { error in
|
133
117
|
XCTAssertEqual(error as? Bowling.BowlingError, .tooManyPinsInFrame)
|
134
118
|
}
|
135
119
|
}
|
136
120
|
|
137
|
-
func
|
138
|
-
|
139
|
-
try? game.roll(pins: 10)
|
140
|
-
try? game.roll(pins: 5)
|
141
|
-
XCTAssertThrowsError(try game.roll(pins: 6)) { error in
|
121
|
+
func testTwoBonusRollsAfterStrike() {
|
122
|
+
XCTAssertThrowsError(try roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6])) { error in
|
142
123
|
XCTAssertEqual(error as? Bowling.BowlingError, .tooManyPinsInFrame)
|
143
124
|
}
|
144
125
|
}
|
145
126
|
|
146
|
-
func
|
127
|
+
func testUnstartedGameCanNotBeScored() {
|
147
128
|
XCTAssertThrowsError(try game.score()) { error in
|
148
129
|
XCTAssertEqual(error as? Bowling.BowlingError, .gameInProgress)
|
149
130
|
}
|
150
131
|
}
|
151
132
|
|
152
|
-
func
|
153
|
-
|
133
|
+
func testIncompleteGameCanNotBeScored() {
|
134
|
+
try? roll([0, 0])
|
135
|
+
|
154
136
|
XCTAssertThrowsError(try game.score()) { error in
|
155
137
|
XCTAssertEqual(error as? Bowling.BowlingError, .gameInProgress)
|
156
138
|
}
|
157
139
|
}
|
158
140
|
|
159
|
-
func
|
160
|
-
|
161
|
-
XCTAssertThrowsError(try game.roll(pins: 0)) { error in
|
141
|
+
func testMoreThanTenFrames() {
|
142
|
+
XCTAssertThrowsError(try roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) { error in
|
162
143
|
XCTAssertEqual(error as? Bowling.BowlingError, .gameIsOver)
|
163
144
|
}
|
164
145
|
}
|
165
146
|
|
166
|
-
func
|
167
|
-
|
147
|
+
func testBonusRollsNotRolled() {
|
148
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10])
|
149
|
+
|
168
150
|
XCTAssertThrowsError(try game.score()) { error in
|
169
151
|
XCTAssertEqual(error as? Bowling.BowlingError, .gameInProgress)
|
170
152
|
}
|
171
153
|
}
|
172
154
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
155
|
+
func testSecondBonusRollNotRolled() {
|
156
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10])
|
157
|
+
|
158
|
+
XCTAssertThrowsError(try game.score()) { error in
|
159
|
+
XCTAssertEqual(error as? Bowling.BowlingError, .gameInProgress)
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
func testBonusRollForSpareNotRolled() {
|
164
|
+
try? roll([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3])
|
165
|
+
|
166
|
+
XCTAssertThrowsError(try game.score()) { error in
|
167
|
+
XCTAssertEqual(error as? Bowling.BowlingError, .gameInProgress)
|
178
168
|
}
|
179
169
|
}
|
180
170
|
|
@@ -2,14 +2,10 @@ import Foundation
|
|
2
2
|
|
3
3
|
private extension String {
|
4
4
|
|
5
|
-
var length: Int {return self.characters.count}
|
5
|
+
var length: Int { return self.characters.count }
|
6
6
|
|
7
7
|
func reverse() -> String {
|
8
|
-
|
9
|
-
for char in self.characters {
|
10
|
-
result = "\(char)\(result)"
|
11
|
-
}
|
12
|
-
return result
|
8
|
+
return characters.reversed().map { String($0) }.joined()
|
13
9
|
}
|
14
10
|
}
|
15
11
|
|
@@ -19,8 +15,8 @@ struct PalindromeProducts {
|
|
19
15
|
private let maxFactor: Int
|
20
16
|
private let minFactor: Int
|
21
17
|
|
22
|
-
var largest: Palindrome {return calculate(.max)}
|
23
|
-
var smallest: Palindrome {return calculate(.min)}
|
18
|
+
var largest: Palindrome { return calculate(.max) }
|
19
|
+
var smallest: Palindrome { return calculate(.min) }
|
24
20
|
|
25
21
|
init(maxFactor: Int, minFactor: Int = 1) {
|
26
22
|
self.maxFactor = maxFactor
|
@@ -31,10 +27,11 @@ struct PalindromeProducts {
|
|
31
27
|
private func calculate(_ upTo: Mode) -> Palindrome {
|
32
28
|
|
33
29
|
let rangeOuter = minFactor...maxFactor
|
34
|
-
var multiplications = [Palindrome]()
|
35
30
|
|
36
31
|
//Multithreaded code
|
37
32
|
var results = [[Palindrome]](repeating: [Palindrome](), count: rangeOuter.count)
|
33
|
+
// use this queue to read and write from results
|
34
|
+
let resultsRWQueue = DispatchQueue.init(label: "exercism.resultsRWQueue")
|
38
35
|
|
39
36
|
DispatchQueue.concurrentPerform(iterations: rangeOuter.count) {
|
40
37
|
advanceByIndex in
|
@@ -49,19 +46,25 @@ struct PalindromeProducts {
|
|
49
46
|
multiplicationsTemp.append((multiplied, [each, eaInside]))
|
50
47
|
}
|
51
48
|
}
|
52
|
-
|
49
|
+
// prevent data race conditions
|
50
|
+
resultsRWQueue.async {
|
51
|
+
results[advanceByIndex] = multiplicationsTemp
|
52
|
+
}
|
53
|
+
}
|
54
|
+
var multiplications = [Palindrome]()
|
55
|
+
// prevent data race conditions
|
56
|
+
resultsRWQueue.sync {
|
57
|
+
multiplications = results.joined().sorted(by: { $0.value > $1.value })
|
53
58
|
}
|
54
|
-
multiplications = results.joined().sorted(by: {$0.0 > $1.0})
|
55
|
-
|
56
59
|
if let large = multiplications.first, let small = multiplications.last {
|
57
60
|
switch upTo {
|
58
|
-
case .max
|
59
|
-
case .min
|
61
|
+
case .max: return large
|
62
|
+
case .min: return small
|
60
63
|
}
|
61
64
|
} else {
|
62
65
|
switch upTo {
|
63
|
-
case .max
|
64
|
-
case .min
|
66
|
+
case .max: return (maxFactor, [maxFactor, 1])
|
67
|
+
case .min: return (minFactor, [minFactor, 1])
|
65
68
|
}
|
66
69
|
}
|
67
70
|
}
|
data/tracks/tcl/README.md
CHANGED
@@ -16,3 +16,6 @@ The MIT License (MIT)
|
|
16
16
|
|
17
17
|
Copyright (c) 2015 Katrina Owen, _@kytrinyx.com
|
18
18
|
|
19
|
+
### Tcl icon
|
20
|
+
The Tcl icon was created by [Fant0men at en.wikipedia](https://en.wikipedia.org/wiki/User:Fant0men) and released under the [Creative Commons Attribution-ShareAlike 3.0 Unported](https://creativecommons.org/licenses/by-sa/3.0/) license.
|
21
|
+
We adapted the icon, creating a black, pink and white version of it to use on Exercism.
|
data/tracks/tcl/config.json
CHANGED
Binary file
|