trackler 2.0.8.2 → 2.0.8.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 628be9992a422198cd22ca843fb2037ba6c03d72
4
- data.tar.gz: 2ee76fac59c86929d2224dcaa3b4ca3843dc7f4b
3
+ metadata.gz: f0c444d7b94d362ffd61d031a2c19aa0648aec67
4
+ data.tar.gz: b89e89a7208130f5c3609cdfc7d489b9049ceb7e
5
5
  SHA512:
6
- metadata.gz: 950598d86876b07601a68378108358eeeceb09dac2a380d8d5cc607eaa8b6282d0ef2dcd660900dcede06a36b1e5d3fed69ae5ed8c522715b3320c68df20b75b
7
- data.tar.gz: 1c2ba152ea54815a1be22d9224f210cfc0b6d0dd402020481666c914569f02b69a36417f7307dddd5ca342fd6ad6df6ea45bce30e9e4b87fb2ba4a4604caee2f
6
+ metadata.gz: 04579958808938ab72cb8921a7c432c814a219a283b375a732da663b2060cf688640a7cd7ca0f185af4d8c5d2874fcd88c51be3ec0db0f39dde08c46f8203e4a
7
+ data.tar.gz: 4b4b7d1cde0197fba10b59031fb9355ee2fa4e4a36f5a131b198df6129516e7891ef05f10f3d4117b909a71d6c3ef27b5b91b1bed520d4288159c294427779cb
@@ -1,134 +1,172 @@
1
1
  {
2
- "#": [
2
+ "exercise": "bowling",
3
+ "version": "1",
4
+ "comments": [
3
5
  "Students should implement roll and score methods.",
4
6
  "Roll should accept a single integer.",
5
7
  "Score should return the game's final score, when possible",
6
- "For brevity the tests display all the rolls in an array;",
7
- "each element of the rolls array should be passed to the roll method",
8
- "The final tests define situations where the score can not be returned",
9
- "The expection for these tests is -1, indicating an error",
10
- "In these cases you should expect an error as is idiomatic for your language",
11
- "When to error is also left up to your implementation. There are two options",
12
- " - Error as soon as an invalid roll is made",
13
- " - Error when scoring a game with an invalid roll",
14
- "You can also error in both cases."
8
+ "For brevity the tests display all the previous rolls in an array;",
9
+ "each element of the previous_rolls array should be passed to the roll method",
10
+ "and each of those previous rolls is expected to succeed.",
11
+ "",
12
+ "Two properties are tested:",
13
+ "",
14
+ "`score`: All rolls succeed, and taking the score gives the expected result.",
15
+ "The expected result may be an integer score or an error.",
16
+ "",
17
+ "`roll`: All previous_rolls succeed, and rolling the number of pins in `roll` produces the expected result.",
18
+ "Currently, all cases of this type result in errors.",
19
+ "",
20
+ "In all error cases you should expect an error as is idiomatic for your language",
21
+ "whether that be via exceptions, optional values, or otherwise."
15
22
  ],
16
- "score": {
17
- "description": [
18
- "returns the final score of a bowling game"
19
- ],
20
- "cases": [{
21
- "description": "should be able to score a game with all zeros",
22
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
23
- "expected": 0
24
- }, {
25
- "description": "should be able to score a game with no strikes or spares",
26
- "rolls": [3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6],
27
- "expected": 90
28
- }, {
29
- "description": "a spare followed by zeros is worth ten points",
30
- "rolls": [6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
31
- "expected": 10
32
- }, {
33
- "description": "points scored in the roll after a spare are counted twice",
34
- "rolls": [6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
35
- "expected": 16
36
- }, {
37
- "description": "consecutive spares each get a one roll bonus",
38
- "rolls": [5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
39
- "expected": 31
40
- }, {
41
- "description": "a spare in the last frame gets a one roll bonus that is counted once",
42
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7],
43
- "expected": 17
44
- }, {
45
- "description": "a strike earns ten points in a frame with a single roll",
46
- "rolls": [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
47
- "expected": 10
48
- }, {
49
- "description": "points scored in the two rolls after a strike are counted twice as a bonus",
50
- "rolls": [10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
51
- "expected": 26
52
- }, {
53
- "description": "consecutive strikes each get the two roll bonus",
54
- "rolls": [10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
55
- "expected": 81
56
- }, {
57
- "description": "a strike in the last frame gets a two roll bonus that is counted once",
58
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1],
59
- "expected": 18
60
- }, {
61
- "description": "rolling a spare with the two roll bonus does not get a bonus roll",
62
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3],
63
- "expected": 20
64
- }, {
65
- "description": "strikes with the two roll bonus do not get bonus rolls",
66
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10],
67
- "expected": 30
68
- }, {
69
- "description": "a strike with the one roll bonus after a spare in the last frame does not get a bonus",
70
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10],
71
- "expected": 20
72
- }, {
73
- "description": "all strikes is a perfect game",
74
- "rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
75
- "expected": 300
76
- }, {
77
- "description": "rolls can not score negative points",
78
- "rolls": [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
79
- "expected": -1
80
- }, {
81
- "description": "a roll can not score more than 10 points",
82
- "rolls": [11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
83
- "expected": -1
84
- }, {
85
- "description": "two rolls in a frame can not score more than 10 points",
86
- "rolls": [5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
87
- "expected": -1
88
- }, {
89
- "description": "bonus roll after a strike in the last frame can not score more than 10 points",
90
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11],
91
- "expected": -1
92
- }, {
93
- "description": "two bonus rolls after a strike in the last frame can not score more than 10 points",
94
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6],
95
- "expected": -1
96
- }, {
97
- "description": "two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike",
98
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6],
99
- "expected": 26
100
- }, {
101
- "description": "the second bonus rolls after a strike in the last frame can not be a strike if the first one is not a strike",
102
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6, 10],
103
- "expected": -1
104
- }, {
105
- "description": "second bonus roll after a strike in the last frame can not score than 10 points",
106
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 11],
107
- "expected": -1
108
- }, {
109
- "description": "an unstarted game can not be scored",
110
- "rolls": [],
111
- "expected": -1
112
- }, {
113
- "description": "an incomplete game can not be scored",
114
- "rolls": [0, 0],
115
- "expected": -1
116
- }, {
117
- "description": "a game with more than ten frames can not be scored",
118
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
119
- "expected": -1
120
- }, {
121
- "description": "bonus rolls for a strike in the last frame must be rolled before score can be calculated",
122
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
123
- "expected": -1
124
- }, {
125
- "description": "both bonus rolls for a strike in the last frame must be rolled before score can be calculated",
126
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10],
127
- "expected": -1
128
- }, {
129
- "description": "bonus roll for a spare in the last frame must be rolled before score can be calculated",
130
- "rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3],
131
- "expected": -1
132
- }]
133
- }
23
+ "cases": [{
24
+ "description": "should be able to score a game with all zeros",
25
+ "property": "score",
26
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
27
+ "expected": 0
28
+ }, {
29
+ "description": "should be able to score a game with no strikes or spares",
30
+ "property": "score",
31
+ "previous_rolls": [3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6],
32
+ "expected": 90
33
+ }, {
34
+ "description": "a spare followed by zeros is worth ten points",
35
+ "property": "score",
36
+ "previous_rolls": [6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
37
+ "expected": 10
38
+ }, {
39
+ "description": "points scored in the roll after a spare are counted twice",
40
+ "property": "score",
41
+ "previous_rolls": [6, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
42
+ "expected": 16
43
+ }, {
44
+ "description": "consecutive spares each get a one roll bonus",
45
+ "property": "score",
46
+ "previous_rolls": [5, 5, 3, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
47
+ "expected": 31
48
+ }, {
49
+ "description": "a spare in the last frame gets a one roll bonus that is counted once",
50
+ "property": "score",
51
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 7],
52
+ "expected": 17
53
+ }, {
54
+ "description": "a strike earns ten points in a frame with a single roll",
55
+ "property": "score",
56
+ "previous_rolls": [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
57
+ "expected": 10
58
+ }, {
59
+ "description": "points scored in the two rolls after a strike are counted twice as a bonus",
60
+ "property": "score",
61
+ "previous_rolls": [10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
62
+ "expected": 26
63
+ }, {
64
+ "description": "consecutive strikes each get the two roll bonus",
65
+ "property": "score",
66
+ "previous_rolls": [10, 10, 10, 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
67
+ "expected": 81
68
+ }, {
69
+ "description": "a strike in the last frame gets a two roll bonus that is counted once",
70
+ "property": "score",
71
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 1],
72
+ "expected": 18
73
+ }, {
74
+ "description": "rolling a spare with the two roll bonus does not get a bonus roll",
75
+ "property": "score",
76
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 3],
77
+ "expected": 20
78
+ }, {
79
+ "description": "strikes with the two roll bonus do not get bonus rolls",
80
+ "property": "score",
81
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10],
82
+ "expected": 30
83
+ }, {
84
+ "description": "a strike with the one roll bonus after a spare in the last frame does not get a bonus",
85
+ "property": "score",
86
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 10],
87
+ "expected": 20
88
+ }, {
89
+ "description": "all strikes is a perfect game",
90
+ "property": "score",
91
+ "previous_rolls": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10],
92
+ "expected": 300
93
+ }, {
94
+ "description": "rolls can not score negative points",
95
+ "property": "roll",
96
+ "previous_rolls": [],
97
+ "roll": -1,
98
+ "expected": {"error": "Negative roll is invalid"}
99
+ }, {
100
+ "description": "a roll can not score more than 10 points",
101
+ "property": "roll",
102
+ "previous_rolls": [],
103
+ "roll": 11,
104
+ "expected": {"error": "Pin count exceeds pins on the lane"}
105
+ }, {
106
+ "description": "two rolls in a frame can not score more than 10 points",
107
+ "property": "roll",
108
+ "previous_rolls": [5],
109
+ "roll": 6,
110
+ "expected": {"error": "Pin count exceeds pins on the lane"}
111
+ }, {
112
+ "description": "bonus roll after a strike in the last frame can not score more than 10 points",
113
+ "property": "roll",
114
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
115
+ "roll": 11,
116
+ "expected": {"error": "Pin count exceeds pins on the lane"}
117
+ }, {
118
+ "description": "two bonus rolls after a strike in the last frame can not score more than 10 points",
119
+ "property": "roll",
120
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5],
121
+ "roll": 6,
122
+ "expected": {"error": "Pin count exceeds pins on the lane"}
123
+ }, {
124
+ "description": "two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike",
125
+ "property": "score",
126
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6],
127
+ "expected": 26
128
+ }, {
129
+ "description": "the second bonus rolls after a strike in the last frame can not be a strike if the first one is not a strike",
130
+ "property": "roll",
131
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6],
132
+ "roll": 10,
133
+ "expected": {"error": "Pin count exceeds pins on the lane"}
134
+ }, {
135
+ "description": "second bonus roll after a strike in the last frame can not score than 10 points",
136
+ "property": "roll",
137
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10],
138
+ "roll": 11,
139
+ "expected": {"error": "Pin count exceeds pins on the lane"}
140
+ }, {
141
+ "description": "an unstarted game can not be scored",
142
+ "property": "score",
143
+ "previous_rolls": [],
144
+ "expected": {"error": "Score cannot be taken until the end of the game"}
145
+ }, {
146
+ "description": "an incomplete game can not be scored",
147
+ "property": "score",
148
+ "previous_rolls": [0, 0],
149
+ "expected": {"error": "Score cannot be taken until the end of the game"}
150
+ }, {
151
+ "description": "cannot roll if game already has ten frames",
152
+ "property": "roll",
153
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
154
+ "roll": 0,
155
+ "expected": {"error": "Cannot roll after game is over"}
156
+ }, {
157
+ "description": "bonus rolls for a strike in the last frame must be rolled before score can be calculated",
158
+ "property": "score",
159
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],
160
+ "expected": {"error": "Score cannot be taken until the end of the game"}
161
+ }, {
162
+ "description": "both bonus rolls for a strike in the last frame must be rolled before score can be calculated",
163
+ "property": "score",
164
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10],
165
+ "expected": {"error": "Score cannot be taken until the end of the game"}
166
+ }, {
167
+ "description": "bonus roll for a spare in the last frame must be rolled before score can be calculated",
168
+ "property": "score",
169
+ "previous_rolls": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3],
170
+ "expected": {"error": "Score cannot be taken until the end of the game"}
171
+ }]
134
172
  }
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.8.2"
2
+ VERSION = "2.0.8.3"
3
3
  end
@@ -8,62 +8,62 @@ public class PangramsTest {
8
8
 
9
9
 
10
10
  @Test
11
- public void sentenceEmpty() {
11
+ public void emptySentenceIsNotPangram() {
12
12
  assertFalse(Pangrams.isPangram(""));
13
13
  }
14
14
 
15
15
  @Ignore
16
16
  @Test
17
- public void pangramWithOnlyLowerCase() {
17
+ public void pangramWithOnlyLowerCaseLettersIsRecognizedAsPangram() {
18
18
  assertTrue(Pangrams.isPangram("the quick brown fox jumps over the lazy dog"));
19
19
  }
20
20
 
21
21
  @Ignore
22
22
  @Test
23
- public void missingCharacterX() {
23
+ public void phraseMissingCharacterXIsNotPangram() {
24
24
  assertFalse(Pangrams.isPangram("a quick movement of the enemy will jeopardize five gunboats"));
25
25
  }
26
26
 
27
27
  @Ignore
28
28
  @Test
29
- public void anotherMissingCharacterX() {
29
+ public void anotherPhraseMissingCharacterXIsNotPangram() {
30
30
  assertFalse(Pangrams.isPangram("the quick brown fish jumps over the lazy dog"));
31
31
  }
32
32
 
33
33
  @Ignore
34
34
  @Test
35
- public void pangramWithUnderscores() {
35
+ public void pangramWithUnderscoresIsRecognizedAsPangram() {
36
36
  assertTrue(Pangrams.isPangram("\"the_quick_brown_fox_jumps_over_the_lazy_dog\""));
37
37
  }
38
38
 
39
39
  @Ignore
40
40
  @Test
41
- public void pangramWithNumbers() {
41
+ public void pangramWithNumbersIsRecognizedAsPangram() {
42
42
  assertTrue(Pangrams.isPangram("\"the 1 quick brown fox jumps over the 2 lazy dogs\""));
43
43
  }
44
44
 
45
45
  @Ignore
46
46
  @Test
47
- public void missingLettersReplacedByNumbers() {
47
+ public void phraseWithMissingLettersReplacedByNumbersIsNotPangram() {
48
48
  assertFalse(Pangrams.isPangram("\"7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog\""));
49
49
  }
50
50
 
51
51
  @Ignore
52
52
  @Test
53
- public void pangramWithMixedCaseAndPunctuation() {
53
+ public void pangramWithMixedCaseAndPunctuationIsRecognizedAsPangram() {
54
54
  assertTrue(Pangrams.isPangram("\"Five quacking Zephyrs jolt my wax bed.\""));
55
55
  }
56
56
 
57
57
  @Ignore
58
58
  @Test
59
- public void pangramWithNonAsciiCharacters() {
59
+ public void pangramWithNonAsciiCharactersIsRecognizedAsPangram() {
60
60
  assertTrue(Pangrams.isPangram("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich."));
61
61
  }
62
62
 
63
63
 
64
64
  @Ignore
65
65
  @Test
66
- public void panagramInAlphabetOtherThanAscii() {
66
+ public void panagramInAlphabetOtherThanAsciiIsNotRecognizedAsPangram() {
67
67
  assertFalse(Pangrams.isPangram("Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства."));
68
68
  }
69
69
 
@@ -228,6 +228,11 @@
228
228
  "slug": "change",
229
229
  "topics": []
230
230
  },
231
+ {
232
+ "difficulty": 1,
233
+ "slug": "triangle",
234
+ "topics": []
235
+ },
231
236
  {
232
237
  "difficulty": 10,
233
238
  "slug": "react",
@@ -40,4 +40,5 @@ include 'isogram'
40
40
  include 'bracket-push'
41
41
  include 'largest-series-product'
42
42
  include 'change'
43
- include 'binary-search'
43
+ include 'binary-search'
44
+ include 'triangle'
@@ -0,0 +1,29 @@
1
+ buildscript {
2
+ ext.kotlin_version = '1.0.6'
3
+ repositories {
4
+ mavenCentral()
5
+ }
6
+ dependencies {
7
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
8
+ }
9
+ }
10
+
11
+ apply plugin: 'kotlin'
12
+
13
+ repositories {
14
+ mavenCentral()
15
+ }
16
+
17
+ dependencies {
18
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
19
+
20
+ testCompile 'junit:junit:4.12'
21
+ testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
22
+ }
23
+
24
+ test {
25
+ testLogging {
26
+ exceptionFormat = 'full'
27
+ events = ["passed", "failed", "skipped"]
28
+ }
29
+ }
@@ -0,0 +1,15 @@
1
+ class Triangle<out T: Number>(val a: T, val b: T, val c: T) {
2
+
3
+ init {
4
+ require(a > 0 && b > 0 && c > 0, {"Sides must be > 0"})
5
+ require(a + b >= c && b + c >= a && c + a >= b, { "Sides must satisfy triangle inequality"})
6
+ }
7
+
8
+ val isEquilateral = a == b && b == c
9
+ val isIsosceles = a == b || b == c || c == a
10
+ val isScalene = !isIsosceles
11
+
12
+ private infix operator fun <T: Number> T.compareTo(other: T): Int = this.toDouble().compareTo(other.toDouble())
13
+ private infix operator fun <T: Number> T.plus(b: T): Double = this.toDouble().plus(b.toDouble())
14
+
15
+ }
@@ -0,0 +1,109 @@
1
+ import org.junit.Ignore
2
+ import org.junit.Test
3
+ import kotlin.test.assertFalse
4
+ import kotlin.test.assertTrue
5
+
6
+ class TriangleTest {
7
+
8
+ @Test
9
+ fun equilateralIfAllSidesAreEqual() {
10
+ assertTrue(Triangle(2, 2, 2).isEquilateral)
11
+ }
12
+
13
+ @Ignore
14
+ @Test
15
+ fun notEquilateralIfAnySideIsUnequal() {
16
+ assertFalse(Triangle(2, 3, 2).isEquilateral)
17
+ }
18
+
19
+ @Ignore
20
+ @Test
21
+ fun notEquilateralIfNoSidesAreEqual() {
22
+ assertFalse(Triangle(5, 4, 6).isEquilateral)
23
+ }
24
+
25
+ @Ignore
26
+ @Test(expected = IllegalArgumentException::class)
27
+ fun allZeroSidesAreIllegalSoNotEquilateral() {
28
+ assertFalse(Triangle(0, 0, 0).isEquilateral)
29
+ }
30
+
31
+ @Ignore
32
+ @Test
33
+ fun equilateralSidesMayBeFloatingPoint() {
34
+ assertTrue(Triangle(0.5, 0.5, 0.5).isEquilateral)
35
+ }
36
+
37
+ @Ignore
38
+ @Test
39
+ fun isoscelesIfLastTwoSidesAreEqual() {
40
+ assertTrue(Triangle(3, 4, 4).isIsosceles)
41
+ }
42
+
43
+ @Ignore
44
+ @Test
45
+ fun isoscelesIfFirstTwoSidesAreEqual() {
46
+ assertTrue(Triangle(4, 4, 3).isIsosceles)
47
+ }
48
+
49
+ @Ignore
50
+ @Test
51
+ fun isoscelesIfFirstAndLastSidesAreEqual() {
52
+ assertTrue(Triangle(4, 3, 4).isIsosceles)
53
+ }
54
+
55
+ @Ignore
56
+ @Test
57
+ fun equilateralIsAlsoIsosceles() {
58
+ assertTrue(Triangle(4, 4, 4).isIsosceles)
59
+ }
60
+
61
+ @Ignore
62
+ @Test
63
+ fun notIsoscelesIfNoSidesAreEqual() {
64
+ assertFalse(Triangle(2, 3, 4).isIsosceles)
65
+ }
66
+
67
+ @Ignore
68
+ @Test(expected = IllegalArgumentException::class)
69
+ fun sidesViolateTriangleInequalitySoNotIsosceles() {
70
+ assertFalse(Triangle(1, 1, 3).isIsosceles)
71
+ }
72
+
73
+ @Ignore
74
+ @Test
75
+ fun isoscelesSidesMayBeFloatingPoint() {
76
+ assertTrue(Triangle(0.5, 0.4, 0.5).isIsosceles)
77
+ }
78
+
79
+ @Ignore
80
+ @Test
81
+ fun scaleneIfNoSidesAreEqual() {
82
+ assertTrue(Triangle(5, 4, 6).isScalene)
83
+ }
84
+
85
+ @Ignore
86
+ @Test
87
+ fun notScaleneIfAllSidesAreEqual() {
88
+ assertFalse(Triangle(4, 4, 4).isScalene)
89
+ }
90
+
91
+ @Ignore
92
+ @Test
93
+ fun notScaleneIfTwoSidesAreEqual() {
94
+ assertFalse(Triangle(4, 4, 3).isScalene)
95
+ }
96
+
97
+ @Ignore
98
+ @Test(expected = IllegalArgumentException::class)
99
+ fun sidesViolateTriangleInequalitySoNotScalene() {
100
+ assertFalse(Triangle(7, 3, 2).isScalene)
101
+ }
102
+
103
+ @Ignore
104
+ @Test
105
+ fun scaleneSidesMayBeFloatingPoint() {
106
+ assertTrue(Triangle(0.5, 0.4, 0.6).isScalene)
107
+ }
108
+
109
+ }
@@ -318,6 +318,14 @@
318
318
  "Tuples"
319
319
  ]
320
320
  },
321
+ {
322
+ "slug":"isogram",
323
+ "difficulty":1,
324
+ "topics":[
325
+ "Strings",
326
+ "Filtering"
327
+ ]
328
+ },
321
329
  {
322
330
  "slug":"bracket-push",
323
331
  "difficulty":1,
@@ -0,0 +1,3 @@
1
+ scalaVersion := "2.12.1"
2
+
3
+ libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test"
@@ -0,0 +1,8 @@
1
+ object Isogram {
2
+ def isIsogram(s: String): Boolean =
3
+ !s.filter(_.isLetter)
4
+ .map(_.toLower)
5
+ .groupBy(identity)
6
+ .values
7
+ .exists(_.length > 1)
8
+ }
@@ -0,0 +1,52 @@
1
+ import org.scalatest.{FunSuite, Matchers}
2
+
3
+ class IsogramTest extends FunSuite with Matchers {
4
+
5
+ test("empty string") {
6
+ val result = Isogram.isIsogram("")
7
+ result should be (true)
8
+ }
9
+
10
+ test("isogram with only lower case characters") {
11
+ pending
12
+ val result = Isogram.isIsogram("isogram")
13
+ result should be (true)
14
+ }
15
+
16
+ test("word with one duplicated character") {
17
+ pending
18
+ val result = Isogram.isIsogram("eleven")
19
+ result should be (false)
20
+ }
21
+
22
+ test("longest reported english isogram") {
23
+ pending
24
+ val result = Isogram.isIsogram("subdermatoglyphic")
25
+ result should be (true)
26
+ }
27
+
28
+ test("word with duplicated character in mixed case") {
29
+ pending
30
+ val result = Isogram.isIsogram("Alphabet")
31
+ result should be (false)
32
+ }
33
+
34
+ test("hypothetical isogrammic word with hyphen") {
35
+ pending
36
+ val result = Isogram.isIsogram("thumbscrew-japingly")
37
+ result should be (true)
38
+ }
39
+
40
+ test("isogram with duplicated non letter character") {
41
+ pending
42
+ val result = Isogram.isIsogram("Hjelmqvist-Gryb-Zock-Pfund-Wax")
43
+ result should be (true)
44
+ }
45
+
46
+ test("made-up name that is an isogram") {
47
+ pending
48
+ val result = Isogram.isIsogram("Emily Jung Schwartzkopf")
49
+ result should be (true)
50
+ }
51
+
52
+ }
@@ -0,0 +1,37 @@
1
+ import play.api.libs.json.Json
2
+
3
+ import scala.io.Source
4
+
5
+ class IsogramTestGenerator {
6
+ implicit val testCaseReader = Json.reads[IsogramTestCase]
7
+
8
+ private val filename = "isogram.json"
9
+ private val fileContents = Source.fromFile(filename).getLines.mkString
10
+ private val json = Json.parse(fileContents)
11
+
12
+ def write {
13
+ val testCases = (json \ "cases").get.as[List[IsogramTestCase]]
14
+
15
+ implicit def testCaseToGen(tc: IsogramTestCase): TestCaseGen = {
16
+ val callSUT =
17
+ s"""Isogram.isIsogram("${tc.input}")"""
18
+ val expected = tc.expected.toString
19
+
20
+ TestCaseGen(tc.description, callSUT, expected)
21
+ }
22
+
23
+ val testBuilder = new TestBuilder("IsogramTest")
24
+ testBuilder.addTestCases(testCases)
25
+ testBuilder.toFile
26
+ }
27
+ }
28
+
29
+ case class IsogramTestCase(description: String,
30
+ input: String,
31
+ expected: Boolean)
32
+
33
+ object IsogramTestGenerator {
34
+ def main(args: Array[String]): Unit = {
35
+ new IsogramTestGenerator().write
36
+ }
37
+ }
@@ -44,11 +44,7 @@ moveAllIntoCommonDir:
44
44
  moveCommonIntoSubDir:
45
45
  @for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) moveAssigmentToSub || exit 1; done
46
46
 
47
- <<<<<<< HEAD
48
- all: replacePackageFileFromCommonToSubFolders
49
- =======
50
47
  all: replacePackageFilesFromCommonToSubFolders
51
- >>>>>>> f5528ecd7751462ac6590cc77304a7ac2489c895
52
48
 
53
49
  copyPackageFilesToSubFolder:
54
50
  @cp ./common/package.json exercises/$(ASSIGNMENT)/package.json
@@ -56,10 +52,6 @@ copyPackageFilesToSubFolder:
56
52
  @cp ./common/tslint.json exercises/$(ASSIGNMENT)/tslint.json
57
53
  @cp ./common/yarn.lock exercises/$(ASSIGNMENT)/yarn.lock
58
54
 
59
- <<<<<<< HEAD
60
- replacePackageFileFromCommonToSubFolders:
61
- =======
62
55
  replacePackageFilesFromCommonToSubFolders:
63
- >>>>>>> f5528ecd7751462ac6590cc77304a7ac2489c895
64
56
  @for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) copyPackageFilesToSubFolder || exit 1; done
65
57
 
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.2
4
+ version: 2.0.8.3
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-02-22 00:00:00.000000000 Z
11
+ date: 2017-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -4602,6 +4602,10 @@ files:
4602
4602
  - tracks/kotlin/exercises/strain/src/example/kotlin/Strain.kt
4603
4603
  - tracks/kotlin/exercises/strain/src/main/kotlin/.keep
4604
4604
  - tracks/kotlin/exercises/strain/src/test/kotlin/StrainTest.kt
4605
+ - tracks/kotlin/exercises/triangle/build.gradle
4606
+ - tracks/kotlin/exercises/triangle/src/example/kotlin/Triangle.kt
4607
+ - tracks/kotlin/exercises/triangle/src/main/kotlin/.keep
4608
+ - tracks/kotlin/exercises/triangle/src/test/kotlin/TriangleTest.kt
4605
4609
  - tracks/kotlin/exercises/word-count/build.gradle
4606
4610
  - tracks/kotlin/exercises/word-count/src/example/kotlin/WordCount.kt
4607
4611
  - tracks/kotlin/exercises/word-count/src/main/kotlin/.keep
@@ -7175,6 +7179,10 @@ files:
7175
7179
  - tracks/scala/exercises/house/example.scala
7176
7180
  - tracks/scala/exercises/house/src/main/scala/.keep
7177
7181
  - tracks/scala/exercises/house/src/test/scala/HouseTest.scala
7182
+ - tracks/scala/exercises/isogram/build.sbt
7183
+ - tracks/scala/exercises/isogram/example.scala
7184
+ - tracks/scala/exercises/isogram/src/main/scala/Isogram.scala
7185
+ - tracks/scala/exercises/isogram/src/test/scala/IsogramTest.scala
7178
7186
  - tracks/scala/exercises/kindergarten-garden/build.sbt
7179
7187
  - tracks/scala/exercises/kindergarten-garden/example.scala
7180
7188
  - tracks/scala/exercises/kindergarten-garden/src/main/scala/.keep
@@ -7388,6 +7396,7 @@ files:
7388
7396
  - tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala
7389
7397
  - tracks/scala/testgen/src/main/scala/BracketPushTestGenerator.scala
7390
7398
  - tracks/scala/testgen/src/main/scala/CustomSetTestGenerator.scala
7399
+ - tracks/scala/testgen/src/main/scala/IsogramTestGenerator.scala
7391
7400
  - tracks/scala/testgen/src/main/scala/PangramsTestGenerator.scala
7392
7401
  - tracks/scala/testgen/src/main/scala/RailFenceCipherTestGenerator.scala
7393
7402
  - tracks/scala/testgen/src/main/scala/TestBuilder.scala