trackler 2.2.1.49 → 2.2.1.50
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/bin/verify-configs +1 -1
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/kindergarten-garden/canonical-data.json +0 -37
- data/tracks/c/exercises/allergies/test/test_allergies.c +41 -41
- data/tracks/common-lisp/config.json +266 -252
- data/tracks/common-lisp/config/maintainers.json +23 -23
- data/tracks/common-lisp/exercises/allergies/README.md +0 -1
- data/tracks/common-lisp/exercises/atbash-cipher/README.md +2 -1
- data/tracks/common-lisp/exercises/beer-song/README.md +1 -1
- data/tracks/common-lisp/exercises/binary/README.md +2 -0
- data/tracks/common-lisp/exercises/collatz-conjecture/README.md +4 -8
- data/tracks/common-lisp/exercises/crypto-square/README.md +4 -4
- data/tracks/common-lisp/exercises/etl/README.md +2 -0
- data/tracks/common-lisp/exercises/grade-school/README.md +0 -1
- data/tracks/common-lisp/exercises/grains/README.md +0 -1
- data/tracks/common-lisp/exercises/leap/README.md +1 -1
- data/tracks/common-lisp/exercises/meetup/README.md +1 -2
- data/tracks/common-lisp/exercises/nucleotide-count/README.md +8 -22
- data/tracks/common-lisp/exercises/pascals-triangle/README.md +1 -1
- data/tracks/common-lisp/exercises/perfect-numbers/README.md +3 -4
- data/tracks/common-lisp/exercises/phone-number/README.md +3 -2
- data/tracks/common-lisp/exercises/roman-numerals/README.md +1 -1
- data/tracks/common-lisp/exercises/scrabble-score/README.md +3 -1
- data/tracks/common-lisp/exercises/space-age/README.md +2 -1
- data/tracks/common-lisp/exercises/sublist/README.md +65 -0
- data/tracks/common-lisp/exercises/sublist/example.lisp +24 -0
- data/tracks/common-lisp/exercises/sublist/sublist-test.lisp +87 -0
- data/tracks/common-lisp/exercises/sublist/sublist.lisp +8 -0
- data/tracks/common-lisp/exercises/triangle/README.md +9 -6
- data/tracks/common-lisp/exercises/trinary/README.md +1 -1
- data/tracks/common-lisp/exercises/word-count/README.md +1 -2
- data/tracks/ecmascript/config.json +30 -0
- data/tracks/ecmascript/exercises/bowling/README.md +80 -0
- data/tracks/ecmascript/exercises/bowling/bowling.spec.js +159 -0
- data/tracks/ecmascript/exercises/bowling/example.js +67 -0
- data/tracks/ecmascript/exercises/bowling/package.json +71 -0
- data/tracks/ecmascript/exercises/two-fer/README.md +47 -0
- data/tracks/ecmascript/exercises/two-fer/example.js +4 -0
- data/tracks/ecmascript/exercises/two-fer/package.json +69 -0
- data/tracks/ecmascript/exercises/two-fer/two-fer.spec.js +18 -0
- data/tracks/fsharp/exercises/pascals-triangle/Example.fs +12 -8
- data/tracks/fsharp/exercises/pascals-triangle/PascalsTriangle.fs +2 -2
- data/tracks/fsharp/exercises/pascals-triangle/PascalsTriangleTest.fs +15 -12
- data/tracks/fsharp/generators/Generators.fs +19 -0
- data/tracks/fsharp/generators/Templates/_AssertThrows.liquid +1 -0
- data/tracks/java/docs/ABOUT.md +13 -31
- data/tracks/java/exercises/bracket-push/.meta/version +1 -1
- data/tracks/java/exercises/bracket-push/src/test/java/BracketCheckerTest.java +7 -1
- data/tracks/java/exercises/collatz-conjecture/.meta/version +1 -1
- data/tracks/java/exercises/etl/README.md +1 -1
- data/tracks/java/exercises/ocr-numbers/README.md +1 -1
- data/tracks/java/exercises/pascals-triangle/README.md +1 -1
- data/tracks/java/exercises/perfect-numbers/.meta/version +1 -1
- data/tracks/java/exercises/rna-transcription/README.md +1 -1
- data/tracks/java/exercises/secret-handshake/.meta/version +1 -1
- data/tracks/java/exercises/secret-handshake/src/test/java/HandshakeCalculatorTest.java +1 -9
- data/tracks/java/scripts/canonical_data_check.sh +104 -0
- data/tracks/javascript/exercises/twelve-days/example.js +23 -25
- data/tracks/julia/.travis.yml +1 -0
- data/tracks/kotlin/exercises/all-your-base/.meta/version +1 -0
- data/tracks/kotlin/exercises/all-your-base/src/test/kotlin/BaseConverterTest.kt +0 -3
- data/tracks/kotlin/exercises/change/.meta/version +1 -0
- data/tracks/kotlin/exercises/change/src/test/kotlin/ChangeCalculatorTest.kt +0 -3
- data/tracks/kotlin/exercises/clock/.meta/version +1 -0
- data/tracks/kotlin/exercises/clock/src/test/kotlin/ClockAddTest.kt +1 -4
- data/tracks/kotlin/exercises/clock/src/test/kotlin/ClockCreationTest.kt +1 -4
- data/tracks/kotlin/exercises/clock/src/test/kotlin/ClockEqualTest.kt +1 -4
- data/tracks/kotlin/exercises/collatz-conjecture/.meta/version +1 -0
- data/tracks/kotlin/exercises/collatz-conjecture/src/test/kotlin/CollatzCalculatorTest.kt +0 -3
- data/tracks/kotlin/exercises/complex-numbers/.meta/version +1 -0
- data/tracks/kotlin/exercises/complex-numbers/src/test/kotlin/ComplexNumberTest.kt +0 -3
- data/tracks/kotlin/exercises/diamond/.meta/version +1 -0
- data/tracks/kotlin/exercises/diamond/src/test/kotlin/DiamondPrinterTest.kt +0 -3
- data/tracks/kotlin/exercises/etl/README.md +1 -1
- data/tracks/kotlin/exercises/forth/.meta/version +1 -0
- data/tracks/kotlin/exercises/forth/src/test/kotlin/ForthEvaluatorTest.kt +0 -3
- data/tracks/kotlin/exercises/grains/.meta/version +1 -0
- data/tracks/kotlin/exercises/grains/src/test/kotlin/BoardTest.kt +0 -3
- data/tracks/kotlin/exercises/hamming/.meta/version +1 -0
- data/tracks/kotlin/exercises/hamming/src/test/kotlin/HammingTest.kt +0 -3
- data/tracks/kotlin/exercises/list-ops/.meta/version +1 -0
- data/tracks/kotlin/exercises/list-ops/src/test/kotlin/ListExtensionsTest.kt +0 -3
- data/tracks/kotlin/exercises/meetup/.meta/version +1 -0
- data/tracks/kotlin/exercises/meetup/src/test/kotlin/MeetupTest.kt +0 -3
- data/tracks/kotlin/exercises/minesweeper/.meta/version +1 -0
- data/tracks/kotlin/exercises/minesweeper/src/test/kotlin/MinesweeperBoardTest.kt +0 -3
- data/tracks/kotlin/exercises/pangram/.meta/version +1 -0
- data/tracks/kotlin/exercises/pangram/src/test/kotlin/PangramTest.kt +0 -3
- data/tracks/kotlin/exercises/pascals-triangle/README.md +1 -1
- data/tracks/kotlin/exercises/prime-factors/.meta/version +1 -0
- data/tracks/kotlin/exercises/prime-factors/src/test/kotlin/PrimeFactorCalculatorTest.kt +0 -3
- data/tracks/kotlin/exercises/rna-transcription/.meta/version +1 -0
- data/tracks/kotlin/exercises/rna-transcription/README.md +1 -1
- data/tracks/kotlin/exercises/rna-transcription/src/test/kotlin/RnaTranscriptionTest.kt +0 -3
- data/tracks/kotlin/exercises/robot-simulator/.meta/version +1 -0
- data/tracks/kotlin/exercises/robot-simulator/src/test/kotlin/RobotTest.kt +0 -3
- data/tracks/kotlin/exercises/rotational-cipher/.meta/version +1 -0
- data/tracks/kotlin/exercises/rotational-cipher/src/test/kotlin/RotationalCipherTest.kt +0 -3
- data/tracks/kotlin/exercises/saddle-points/.meta/version +1 -0
- data/tracks/kotlin/exercises/saddle-points/src/test/kotlin/MatrixTest.kt +0 -3
- data/tracks/kotlin/exercises/say/.meta/version +1 -0
- data/tracks/kotlin/exercises/say/src/test/kotlin/NumberSpellerTest.kt +0 -3
- data/tracks/kotlin/exercises/secret-handshake/.meta/version +1 -0
- data/tracks/kotlin/exercises/secret-handshake/src/test/kotlin/HandshakeCalculatorTest.kt +0 -3
- data/tracks/kotlin/exercises/spiral-matrix/.meta/version +1 -0
- data/tracks/kotlin/exercises/spiral-matrix/src/test/kotlin/SpiralMatrixTest.kt +0 -3
- data/tracks/kotlin/exercises/sublist/.meta/version +1 -0
- data/tracks/kotlin/exercises/sublist/src/test/kotlin/SublistTest.kt +0 -3
- data/tracks/kotlin/scripts/canonical_data_check.sh +104 -0
- data/tracks/perl6/exercises/accumulate/accumulate.t +2 -3
- data/tracks/perl6/exercises/all-your-base/all-your-base.t +17 -18
- data/tracks/perl6/exercises/allergies/allergies.t +17 -18
- data/tracks/perl6/exercises/anagram/anagram.t +17 -18
- data/tracks/perl6/exercises/atbash-cipher/atbash-cipher.t +17 -18
- data/tracks/perl6/exercises/bob/bob.t +20 -22
- data/tracks/perl6/exercises/bob/example.yaml +1 -2
- data/tracks/perl6/exercises/clock/clock.t +17 -18
- data/tracks/perl6/exercises/flatten-array/flatten-array.t +17 -18
- data/tracks/perl6/exercises/grade-school/grade-school.t +2 -3
- data/tracks/perl6/exercises/grains/grains.t +17 -18
- data/tracks/perl6/exercises/hello-world/example.yaml +1 -2
- data/tracks/perl6/exercises/hello-world/hello-world.t +20 -22
- data/tracks/perl6/exercises/leap/leap.t +17 -18
- data/tracks/perl6/exercises/linked-list/linked-list.t +2 -3
- data/tracks/perl6/exercises/luhn/luhn.t +17 -18
- data/tracks/perl6/exercises/phone-number/phone-number.t +17 -18
- data/tracks/perl6/exercises/raindrops/raindrops.t +17 -18
- data/tracks/perl6/exercises/rna-transcription/rna-transcription.t +17 -18
- data/tracks/perl6/exercises/robot-name/robot-name.t +2 -3
- data/tracks/perl6/exercises/scrabble-score/scrabble-score.t +17 -18
- data/tracks/perl6/exercises/space-age/space-age.t +17 -18
- data/tracks/perl6/exercises/word-count/word-count.t +17 -18
- data/tracks/perl6/exercises/wordy/wordy.t +17 -18
- data/tracks/perl6/templates/test.mustache +9 -10
- data/tracks/purescript/config.json +11 -0
- data/tracks/purescript/exercises/rna-transcription/README.md +25 -0
- data/tracks/purescript/exercises/rna-transcription/bower.json +26 -0
- data/tracks/purescript/exercises/rna-transcription/examples/src/RNATranscription.purs +18 -0
- data/tracks/purescript/exercises/rna-transcription/src/RNATranscription.purs +3 -0
- data/tracks/purescript/exercises/rna-transcription/test/Main.purs +48 -0
- data/tracks/python/exercises/variable-length-quantity/example.py +6 -6
- data/tracks/python/exercises/variable-length-quantity/variable_length_quantity.py +2 -2
- data/tracks/ruby/config.json +6 -0
- data/tracks/ruby/exercises/complex-numbers/.meta/.version +1 -0
- data/tracks/ruby/exercises/complex-numbers/.meta/generator/complex_numbers_case.rb +44 -0
- data/tracks/ruby/exercises/complex-numbers/.meta/solutions/complex_numbers.rb +49 -0
- data/tracks/ruby/exercises/complex-numbers/README.md +64 -0
- data/tracks/ruby/exercises/complex-numbers/complex_numbers_test.rb +207 -0
- data/tracks/ruby/exercises/crypto-square/.meta/.version +1 -0
- data/tracks/ruby/exercises/crypto-square/.meta/generator/crypto_square_case.rb +19 -0
- data/tracks/ruby/exercises/crypto-square/.meta/solutions/crypto_square.rb +20 -15
- data/tracks/ruby/exercises/crypto-square/README.md +10 -8
- data/tracks/ruby/exercises/crypto-square/crypto_square_test.rb +45 -81
- data/tracks/ruby/exercises/flatten-array/.meta/.version +1 -0
- data/tracks/ruby/exercises/flatten-array/.meta/generator/flatten_array_case.rb +11 -0
- data/tracks/ruby/exercises/flatten-array/.meta/solutions/flatten_array.rb +5 -2
- data/tracks/ruby/exercises/flatten-array/flatten_array_test.rb +32 -7
- data/tracks/ruby/exercises/hamming/hamming_test.rb +3 -3
- data/tracks/ruby/exercises/isogram/isogram_test.rb +4 -4
- data/tracks/ruby/exercises/leap/leap_test.rb +2 -2
- data/tracks/ruby/exercises/pig-latin/.meta/.version +1 -1
- data/tracks/ruby/exercises/pig-latin/.meta/solutions/pig_latin.rb +2 -2
- data/tracks/ruby/exercises/pig-latin/pig_latin_test.rb +17 -7
- data/tracks/ruby/exercises/queen-attack/.meta/generator/queen_attack_case.rb +1 -1
- data/tracks/ruby/exercises/queen-attack/queen_attack_test.rb +7 -7
- data/tracks/ruby/exercises/sum-of-multiples/.meta/.version +1 -1
- data/tracks/ruby/exercises/sum-of-multiples/.meta/solutions/sum_of_multiples.rb +1 -1
- data/tracks/ruby/exercises/sum-of-multiples/sum_of_multiples_test.rb +7 -2
- metadata +53 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
(defpackage #:sublist
|
|
2
|
+
(:use #:common-lisp)
|
|
3
|
+
(:export #:sublist))
|
|
4
|
+
|
|
5
|
+
(in-package #:sublist)
|
|
6
|
+
|
|
7
|
+
(defun is-prefix-of (xs ys)
|
|
8
|
+
(cond ((null xs) T)
|
|
9
|
+
((null ys) NIL)
|
|
10
|
+
((equal (car xs) (car ys)) (is-prefix-of (cdr xs) (cdr ys)))
|
|
11
|
+
(T NIL)))
|
|
12
|
+
|
|
13
|
+
(defun sublist-of (xs ys)
|
|
14
|
+
(if (and xs (null ys))
|
|
15
|
+
nil
|
|
16
|
+
(or (is-prefix-of xs ys) (sublist-of xs (cdr ys)))))
|
|
17
|
+
|
|
18
|
+
(defun sublist (xs ys)
|
|
19
|
+
(let ((sub (sublist-of xs ys))
|
|
20
|
+
(super (sublist-of ys xs)))
|
|
21
|
+
(cond ((and sub super) "equal")
|
|
22
|
+
(sub "sublist")
|
|
23
|
+
(super "superlist")
|
|
24
|
+
(T "unequal"))))
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
(ql:quickload "lisp-unit")
|
|
2
|
+
#-xlisp-test (load "sublist")
|
|
3
|
+
|
|
4
|
+
(defpackage #:sublist-test
|
|
5
|
+
(:use #:common-lisp #:lisp-unit))
|
|
6
|
+
|
|
7
|
+
(in-package #:sublist-test)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
;; Equal lists tests:
|
|
11
|
+
(define-test empty-lists
|
|
12
|
+
(assert-equal "equal" (sublist:sublist (list)
|
|
13
|
+
(list))))
|
|
14
|
+
|
|
15
|
+
(define-test list-equals-itself
|
|
16
|
+
(assert-equal "equal" (sublist:sublist (list 1 2 3)
|
|
17
|
+
(list 1 2 3))))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
;; Unequal lists tests:
|
|
21
|
+
(define-test different-lists
|
|
22
|
+
(assert-equal "unequal" (sublist:sublist (list 1 2 3)
|
|
23
|
+
(list 2 3 4))))
|
|
24
|
+
|
|
25
|
+
(define-test first-list-missing-element-from-second-list
|
|
26
|
+
(assert-equal "unequal" (sublist:sublist (list 1 3)
|
|
27
|
+
(list 1 2 3))))
|
|
28
|
+
|
|
29
|
+
(define-test second-list-missing-element-from-first-list
|
|
30
|
+
(assert-equal "unequal" (sublist:sublist (list 1 2 3)
|
|
31
|
+
(list 1 3))))
|
|
32
|
+
|
|
33
|
+
(define-test order-matters-to-a-lists
|
|
34
|
+
(assert-equal "unequal" (sublist:sublist (list 1 2 3)
|
|
35
|
+
(list 3 2 1))))
|
|
36
|
+
|
|
37
|
+
(define-test same-digits-different-numbers
|
|
38
|
+
(assert-equal "unequal" (sublist:sublist (list 1 0 1)
|
|
39
|
+
(list 10 1))))
|
|
40
|
+
|
|
41
|
+
;; Sublist lists tests:
|
|
42
|
+
(define-test empty-list-within-non-empty-list
|
|
43
|
+
(assert-equal "sublist" (sublist:sublist (list)
|
|
44
|
+
(list 1 2 3))))
|
|
45
|
+
|
|
46
|
+
(define-test false-start
|
|
47
|
+
(assert-equal "sublist" (sublist:sublist (list 1 2 5)
|
|
48
|
+
(list 0 1 2 3 1 2 5 6))))
|
|
49
|
+
|
|
50
|
+
(define-test consecutive
|
|
51
|
+
(assert-equal "sublist" (sublist:sublist (list 1 1 2)
|
|
52
|
+
(list 0 1 1 1 2 1 2))))
|
|
53
|
+
|
|
54
|
+
(define-test sublist-at-start
|
|
55
|
+
(assert-equal "sublist" (sublist:sublist (list 0 1 2)
|
|
56
|
+
(list 0 1 2 3 4 5))))
|
|
57
|
+
|
|
58
|
+
(define-test sublist-in-middle
|
|
59
|
+
(assert-equal "sublist" (sublist:sublist (list 2 3 4)
|
|
60
|
+
(list 0 1 2 3 4 5))))
|
|
61
|
+
|
|
62
|
+
(define-test sublist-at-end
|
|
63
|
+
(assert-equal "sublist" (sublist:sublist (list 3 4 5)
|
|
64
|
+
(list 0 1 2 3 4 5))))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
;; Superlist lists tests:
|
|
68
|
+
(define-test not-empty-list-contains-empty-list
|
|
69
|
+
(assert-equal "superlist" (sublist:sublist (list 1 2 3)
|
|
70
|
+
(list))))
|
|
71
|
+
|
|
72
|
+
(define-test at-start-of-superlist
|
|
73
|
+
(assert-equal "superlist" (sublist:sublist (list 0 1 2 3 4 5)
|
|
74
|
+
(list 0 1 2))))
|
|
75
|
+
|
|
76
|
+
(define-test in-middle-of-superlist
|
|
77
|
+
(assert-equal "superlist" (sublist:sublist (list 0 1 2 3 4 5)
|
|
78
|
+
(list 2 3))))
|
|
79
|
+
|
|
80
|
+
(define-test at-end-superlist
|
|
81
|
+
(assert-equal "superlist" (sublist:sublist (list 0 1 2 3 4 5)
|
|
82
|
+
(list 3 4 5))))
|
|
83
|
+
|
|
84
|
+
#-xlisp-test
|
|
85
|
+
(let ((*print-errors* t)
|
|
86
|
+
(*print-failures* t))
|
|
87
|
+
(run-tests :all))
|
|
@@ -2,23 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
Determine if a triangle is equilateral, isosceles, or scalene.
|
|
4
4
|
|
|
5
|
-
An _equilateral_ triangle has all three sides the same length
|
|
5
|
+
An _equilateral_ triangle has all three sides the same length.
|
|
6
|
+
|
|
6
7
|
An _isosceles_ triangle has at least two sides the same length. (It is sometimes
|
|
7
8
|
specified as having exactly two sides the same length, but for the purposes of
|
|
8
|
-
this exercise we'll say at least two.)
|
|
9
|
+
this exercise we'll say at least two.)
|
|
10
|
+
|
|
9
11
|
A _scalene_ triangle has all sides of different lengths.
|
|
10
12
|
|
|
11
13
|
## Note
|
|
12
14
|
|
|
13
|
-
For a shape to be a triangle at all, all sides have to be of length > 0, and
|
|
14
|
-
the sum of the lengths of any two sides must be greater than or equal to the
|
|
15
|
+
For a shape to be a triangle at all, all sides have to be of length > 0, and
|
|
16
|
+
the sum of the lengths of any two sides must be greater than or equal to the
|
|
15
17
|
length of the third side. See [Triangle Inequality](https://en.wikipedia.org/wiki/Triangle_inequality).
|
|
16
18
|
|
|
17
19
|
## Dig Deeper
|
|
18
20
|
|
|
19
|
-
The case where the sum of the lengths of two sides _equals_ that of the
|
|
20
|
-
third is known as a _degenerate_ triangle - it has zero area and looks like
|
|
21
|
+
The case where the sum of the lengths of two sides _equals_ that of the
|
|
22
|
+
third is known as a _degenerate_ triangle - it has zero area and looks like
|
|
21
23
|
a single line. Feel free to add your own code/tests to check for degenerate triangles.
|
|
24
|
+
|
|
22
25
|
## Setup
|
|
23
26
|
|
|
24
27
|
Check out [Exercism Help](http://exercism.io/languages/lisp) for instructions to
|
|
@@ -11,7 +11,7 @@ Trinary numbers contain three symbols: 0, 1, and 2.
|
|
|
11
11
|
The last place in a trinary number is the 1's place. The second to last
|
|
12
12
|
is the 3's place, the third to last is the 9's place, etc.
|
|
13
13
|
|
|
14
|
-
```
|
|
14
|
+
```shell
|
|
15
15
|
# "102012"
|
|
16
16
|
1 0 2 0 1 2 # the number
|
|
17
17
|
1*3^5 + 0*3^4 + 2*3^3 + 0*3^2 + 1*3^1 + 2*3^0 # the value
|
|
@@ -4,14 +4,13 @@ Given a phrase, count the occurrences of each word in that phrase.
|
|
|
4
4
|
|
|
5
5
|
For example for the input `"olly olly in come free"`
|
|
6
6
|
|
|
7
|
-
```
|
|
7
|
+
```text
|
|
8
8
|
olly: 2
|
|
9
9
|
in: 1
|
|
10
10
|
come: 1
|
|
11
11
|
free: 1
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
## Setup
|
|
16
15
|
|
|
17
16
|
Check out [Exercism Help](http://exercism.io/languages/lisp) for instructions to
|
|
@@ -236,6 +236,20 @@
|
|
|
236
236
|
"Recursion"
|
|
237
237
|
]
|
|
238
238
|
},
|
|
239
|
+
{
|
|
240
|
+
"uuid": "207af8f6-0ffe-e380-d521-7e054bd4e959257c77d",
|
|
241
|
+
"slug": "two-fer",
|
|
242
|
+
"core": false,
|
|
243
|
+
"unlocked_by": "hello-world",
|
|
244
|
+
"difficulty": 1,
|
|
245
|
+
"topics": [
|
|
246
|
+
"Booleans",
|
|
247
|
+
"Strings",
|
|
248
|
+
"Logic",
|
|
249
|
+
"Optional values",
|
|
250
|
+
"Text formatting"
|
|
251
|
+
]
|
|
252
|
+
},
|
|
239
253
|
{
|
|
240
254
|
"uuid": "d773c4ef-c09e-40e4-a7fe-01456cb4a12a",
|
|
241
255
|
"slug": "hamming",
|
|
@@ -980,6 +994,22 @@
|
|
|
980
994
|
"Exception handling"
|
|
981
995
|
]
|
|
982
996
|
},
|
|
997
|
+
{
|
|
998
|
+
"core": false,
|
|
999
|
+
"difficulty": 8,
|
|
1000
|
+
"slug": "bowling",
|
|
1001
|
+
"topics": [
|
|
1002
|
+
"arrays",
|
|
1003
|
+
"control-flow-(conditionals)",
|
|
1004
|
+
"control-flow-(loops)",
|
|
1005
|
+
"exception-handling",
|
|
1006
|
+
"games",
|
|
1007
|
+
"parsing",
|
|
1008
|
+
"text-formatting"
|
|
1009
|
+
],
|
|
1010
|
+
"unlocked_by": "grade-school",
|
|
1011
|
+
"uuid": "dbf26ef1-62ff-4cb1-8ac7-09b022df3b2f"
|
|
1012
|
+
},
|
|
983
1013
|
{
|
|
984
1014
|
"uuid": "6a1eee0e-f8d4-446d-9c52-f31c3700af1b",
|
|
985
1015
|
"slug": "diamond",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Bowling
|
|
2
|
+
|
|
3
|
+
Score a bowling game.
|
|
4
|
+
|
|
5
|
+
Bowling is game where players roll a heavy ball to knock down pins
|
|
6
|
+
arranged in a triangle. Write code to keep track of the score
|
|
7
|
+
of a game of bowling.
|
|
8
|
+
|
|
9
|
+
## Scoring Bowling
|
|
10
|
+
|
|
11
|
+
A game consists of 10 frames. A frame is composed of one or two balls thrown, with 10 pins standing at the start of the frame. There are three cases for the tabulation of a frame:
|
|
12
|
+
|
|
13
|
+
* An open frame is where a score of less than 10 is recorded for the frame. In this case the score for the frame is the number of pins knocked down after the second throw.
|
|
14
|
+
|
|
15
|
+
* A spare is where all ten pins are knocked down after the second throw. The total value of a spare is 10 plus the number of pins knocked down in the next throw.
|
|
16
|
+
|
|
17
|
+
* A strike is where all ten pins are knocked down after the first throw. The total value of a strike is 10 plus the number of pins knocked down in the next two throws. If a strike is immediately followed by another strike, then the first strike's value cannot be totalled until the next throw.
|
|
18
|
+
|
|
19
|
+
Here is a three frame example:
|
|
20
|
+
|
|
21
|
+
| Frame 1 | Frame 2 | Frame 3 |
|
|
22
|
+
| :-------------: |:-------------:| :---------------------:|
|
|
23
|
+
| X (strike) | 5/ (spare) | 9 0 (open frame) |
|
|
24
|
+
|
|
25
|
+
Frame 1 is (10 + 5 + 5) = 20
|
|
26
|
+
|
|
27
|
+
Frame 2 is (5 + 5 + 9) = 19
|
|
28
|
+
|
|
29
|
+
Frame 3 is (9 + 0) = 9
|
|
30
|
+
|
|
31
|
+
This means the current running total is 48.
|
|
32
|
+
|
|
33
|
+
The tenth frame in the game is a special case. If the player throws a strike or a spare, then they get one extra throw called a fill ball. Fill balls exist to calculate the total of the 10th frame. Scoring a strike or spare on the fill ball does not give the player more fill balls. The total value of the 10th frame is the total number of pins knocked down.
|
|
34
|
+
|
|
35
|
+
For a tenth frame of X1/ (strike and a spare), the total value is 20.
|
|
36
|
+
|
|
37
|
+
For a tenth frame of XXX (three strikes), the total value is 30.
|
|
38
|
+
|
|
39
|
+
## Setup
|
|
40
|
+
|
|
41
|
+
Go through the setup instructions for ECMAScript to
|
|
42
|
+
install the necessary dependencies:
|
|
43
|
+
|
|
44
|
+
http://exercism.io/languages/ecmascript
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
Install assignment dependencies:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
$ npm install
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Write code to keep track of the score of a game of bowling. It should
|
|
55
|
+
support two operations:
|
|
56
|
+
|
|
57
|
+
* `roll(pins : int)` is called each time the player rolls a ball. The
|
|
58
|
+
argument is the number of pins knocked down.
|
|
59
|
+
* `score() : int` is called only at the very end of the game. It
|
|
60
|
+
returns the total score for that game.
|
|
61
|
+
|
|
62
|
+
## Making the test suite pass
|
|
63
|
+
|
|
64
|
+
Execute the tests with:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
$ npm test
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
In the test suites all tests but the first have been skipped.
|
|
71
|
+
|
|
72
|
+
Once you get a test passing, you can enable the next one by
|
|
73
|
+
changing `xtest` to `test`.
|
|
74
|
+
|
|
75
|
+
## Source
|
|
76
|
+
|
|
77
|
+
The Bowling Game Kata at but UncleBob [http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata](http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata)
|
|
78
|
+
|
|
79
|
+
## Submitting Incomplete Solutions
|
|
80
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import Bowling from './bowling';
|
|
2
|
+
|
|
3
|
+
describe('Bowling', () => {
|
|
4
|
+
describe('Check game can be scored correctly.', () => {
|
|
5
|
+
test('should be able to score a game with all gutterballs', () => {
|
|
6
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
7
|
+
expect(new Bowling(rolls).score()).toEqual(0);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
xtest('should be able to score a game with all open frames', () => {
|
|
11
|
+
const rolls = [3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6];
|
|
12
|
+
expect(new Bowling(rolls).score()).toEqual(90);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
xtest('a spare followed by zeros is worth ten points', () => {
|
|
16
|
+
const rolls = [6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
17
|
+
expect(new Bowling(rolls).score()).toEqual(10);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
xtest('points scored in the roll after a spare are counted twice', () => {
|
|
21
|
+
const rolls = [6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
22
|
+
expect(new Bowling(rolls).score()).toEqual(16);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
xtest('consecutive spares each get a one roll bonus', () => {
|
|
26
|
+
const rolls = [5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
27
|
+
expect(new Bowling(rolls).score()).toEqual(31);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
xtest('should allow fill ball when the last frame is a spare', () => {
|
|
31
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7];
|
|
32
|
+
expect(new Bowling(rolls).score()).toEqual(17);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
xtest('a strike earns ten points in a frame with a single roll', () => {
|
|
36
|
+
const rolls = [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
37
|
+
expect(new Bowling(rolls).score()).toEqual(10);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
xtest('points scored in the two rolls after a strike are counted twice as a bonus', () => {
|
|
41
|
+
const rolls = [10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
42
|
+
expect(new Bowling(rolls).score()).toEqual(26);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
xtest('should be able to score multiple strikes in a row', () => {
|
|
46
|
+
const rolls = [10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
47
|
+
expect(new Bowling(rolls).score()).toEqual(81);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
xtest('should allow fill balls when the last frame is a strike', () => {
|
|
51
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1];
|
|
52
|
+
expect(new Bowling(rolls).score()).toEqual(18);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
xtest('rolling a spare with the two roll bonus does not get a bonus roll', () => {
|
|
56
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3];
|
|
57
|
+
expect(new Bowling(rolls).score()).toEqual(20);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
xtest('strikes with the two roll bonus do not get bonus rolls', () => {
|
|
61
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10];
|
|
62
|
+
expect(new Bowling(rolls).score()).toEqual(30);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
xtest('a strike with the one roll bonus after a spare in the last frame does not get a bonus', () => {
|
|
66
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10];
|
|
67
|
+
expect(new Bowling(rolls).score()).toEqual(20);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
xtest('should be able to score a perfect game', () => {
|
|
71
|
+
const rolls = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10];
|
|
72
|
+
expect(new Bowling(rolls).score()).toEqual(300);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('Check game rules.', () => {
|
|
77
|
+
xtest('rolls can not score negative points', () => {
|
|
78
|
+
const rolls = [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
79
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
80
|
+
new Error('Pins must have a value from 0 to 10'),
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
xtest('a roll can not score more than 10 points', () => {
|
|
85
|
+
const rolls = [11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
86
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
87
|
+
new Error('Pins must have a value from 0 to 10'),
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
xtest('two rolls in a frame can not score more than 10 points', () => {
|
|
92
|
+
const rolls = [5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
93
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
94
|
+
new Error('Pin count exceeds pins on the lane'),
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
xtest('two bonus rolls after a strike in the last frame can not score more than 10 points', () => {
|
|
99
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6];
|
|
100
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
101
|
+
new Error('Pin count exceeds pins on the lane'),
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
xtest('two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike', () => {
|
|
106
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6];
|
|
107
|
+
expect(new Bowling(rolls).score()).toEqual(26);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
xtest('the second bonus rolls after a strike in the last frame can not be a strike if the first one is not a strike', () => {
|
|
111
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6, 10];
|
|
112
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
113
|
+
new Error('Pin count exceeds pins on the lane'),
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
xtest('an unstarted game can not be scored', () => {
|
|
118
|
+
const rolls = [];
|
|
119
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
120
|
+
new Error('Score cannot be taken until the end of the game'),
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
xtest('an incomplete game can not be scored', () => {
|
|
125
|
+
const rolls = [0, 0];
|
|
126
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
127
|
+
new Error('Score cannot be taken until the end of the game'),
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
xtest('a game with more than ten frames and no last frame spare or strike can not be scored', () => {
|
|
132
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
133
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
134
|
+
new Error('Should not be able to roll after game is over'),
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
xtest('bonus rolls for a strike in the last frame must be rolled before score can be calculated', () => {
|
|
139
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10];
|
|
140
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
141
|
+
new Error('Score cannot be taken until the end of the game'),
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
xtest('both bonus rolls for a strike in the last frame must be rolled before score can be calculated', () => {
|
|
146
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10];
|
|
147
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
148
|
+
new Error('Score cannot be taken until the end of the game'),
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
xtest('bonus roll for a spare in the last frame must be rolled before score can be calculated', () => {
|
|
153
|
+
const rolls = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3];
|
|
154
|
+
expect(() => { new Bowling(rolls).score(); }).toThrow(
|
|
155
|
+
new Error('Score cannot be taken until the end of the game'),
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|