trackler 2.2.1.60 → 2.2.1.61
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/beer-song/canonical-data.json +366 -31
- data/problem-specifications/exercises/beer-song/description.md +1 -1
- data/problem-specifications/exercises/pascals-triangle/canonical-data.json +19 -1
- data/problem-specifications/exercises/proverb/canonical-data.json +91 -0
- data/problem-specifications/exercises/proverb/description.md +5 -3
- data/tracks/c/README.md +0 -10
- data/tracks/c/config/maintainers.json +45 -0
- data/tracks/c/config.json +1 -2
- data/tracks/c/docs/TESTS.md +43 -44
- data/tracks/d/docs/INSTALLATION.md +1 -1
- data/tracks/delphi/exercises/beer-song/README.md +1 -1
- data/tracks/delphi/exercises/beer-song/inputdata.txt +3 -1
- data/tracks/delphi/exercises/beer-song/uBeerSongExample.pas +14 -5
- data/tracks/delphi/exercises/beer-song/uBeerSongTests.pas +58 -42
- data/tracks/delphi/exercises/nucleotide-count/README.md +2 -2
- data/tracks/ecmascript/config.json +14 -0
- data/tracks/ecmascript/exercises/house/README.md +146 -0
- data/tracks/ecmascript/exercises/house/example.js +62 -0
- data/tracks/ecmascript/exercises/house/house.spec.js +292 -0
- data/tracks/ecmascript/exercises/house/package.json +71 -0
- data/tracks/go/exercises/allergies/example.go +3 -2
- data/tracks/go/exercises/custom-set/cases_test.go +7 -2
- data/tracks/go/exercises/isogram/.meta/gen.go +55 -0
- data/tracks/go/exercises/isogram/cases_test.go +57 -0
- data/tracks/go/exercises/isogram/isogram_test.go +4 -20
- data/tracks/java/config.json +7 -1
- data/tracks/java/exercises/luhn/src/test/java/LuhnValidatorTest.java +6 -1
- data/tracks/javascript/.eslintignore +0 -3
- data/tracks/javascript/exercises/acronym/example.js +2 -1
- data/tracks/javascript/exercises/diamond/diamond.spec.js +3 -3
- data/tracks/javascript/exercises/diamond/example.js +2 -2
- data/tracks/javascript/exercises/sum-of-multiples/sum-of-multiples.spec.js +9 -9
- data/tracks/python/config.json +33 -11
- data/tracks/python/exercises/dominoes/README.md +28 -0
- data/tracks/python/exercises/dominoes/dominoes.py +2 -0
- data/tracks/python/exercises/dominoes/dominoes_test.py +114 -0
- data/tracks/python/exercises/dominoes/example.py +30 -0
- data/tracks/python/exercises/grains/grains_test.py +5 -7
- data/tracks/python/exercises/phone-number/example.py +7 -13
- data/tracks/python/exercises/phone-number/phone_number_test.py +15 -15
- data/tracks/python/exercises/poker/poker_test.py +93 -52
- data/tracks/python/exercises/react/README.md +30 -0
- data/tracks/python/exercises/react/example.py +65 -0
- data/tracks/python/exercises/react/react.py +17 -0
- data/tracks/python/exercises/react/react_test.py +136 -0
- data/tracks/rust/exercises/pascals-triangle/Cargo.toml +1 -1
- data/tracks/rust/exercises/pascals-triangle/tests/pascals-triangle.rs +56 -0
- data/tracks/swift/Package.swift +1 -1
- data/tracks/swift/config.json +11 -0
- data/tracks/swift/exercises/atbash-cipher/Sources/AtbashExample.swift +1 -1
- data/tracks/swift/exercises/bracket-push/Sources/BracketPushExample.swift +1 -1
- data/tracks/swift/exercises/collatz-conjecture/Package.swift +5 -0
- data/tracks/swift/exercises/collatz-conjecture/README.md +41 -0
- data/tracks/swift/exercises/collatz-conjecture/Sources/CollatzConjecture.swift +1 -0
- data/tracks/swift/exercises/collatz-conjecture/Sources/CollatzConjectureExample.swift +27 -0
- data/tracks/swift/exercises/collatz-conjecture/Tests/CollatzConjectureTests/CollatzConjectureTests.swift +40 -0
- data/tracks/swift/exercises/collatz-conjecture/Tests/LinuxMain.swift +6 -0
- data/tracks/swift/exercises/dominoes/Sources/DominoesExample.swift +3 -3
- data/tracks/swift/exercises/grains/Tests/GrainsTests/GrainsTests.swift +3 -3
- data/tracks/swift/exercises/kindergarten-garden/Sources/KindergartenGardenExample.swift +2 -2
- data/tracks/swift/exercises/meetup/Sources/MeetupExample.swift +1 -1
- data/tracks/swift/exercises/nucleotide-count/Sources/NucleotideCountExample.swift +2 -2
- data/tracks/swift/exercises/poker/Sources/PokerExample.swift +137 -131
- data/tracks/swift/exercises/rna-transcription/Sources/RnaTranscriptionExample.swift +2 -2
- data/tracks/swift/exercises/rotational-cipher/Sources/RotationalCipherExample.swift +12 -12
- metadata +24 -2
@@ -4,12 +4,12 @@ describe('Diamond', function () {
|
|
4
4
|
var diamond = new Diamond();
|
5
5
|
|
6
6
|
it('test letter A', function () {
|
7
|
-
result = 'A\n';
|
7
|
+
var result = 'A\n';
|
8
8
|
expect(diamond.makeDiamond('A')).toEqual(result);
|
9
9
|
});
|
10
10
|
|
11
11
|
it('test letter C', function () {
|
12
|
-
result = [' A ',
|
12
|
+
var result = [' A ',
|
13
13
|
' B B ',
|
14
14
|
'C C',
|
15
15
|
' B B ',
|
@@ -18,7 +18,7 @@ describe('Diamond', function () {
|
|
18
18
|
});
|
19
19
|
|
20
20
|
it('test letter E', function () {
|
21
|
-
result = [' A ',
|
21
|
+
var result = [' A ',
|
22
22
|
' B B ',
|
23
23
|
' C C ',
|
24
24
|
' D D ',
|
@@ -5,8 +5,8 @@ var Diamond = function () {
|
|
5
5
|
for (var i = 0; i <= inputIndex; i++) {
|
6
6
|
output += getLine(inputIndex, i);
|
7
7
|
}
|
8
|
-
for (var
|
9
|
-
output += getLine(inputIndex,
|
8
|
+
for (var j = inputIndex - 1; j >= 0; j--) {
|
9
|
+
output += getLine(inputIndex, j);
|
10
10
|
}
|
11
11
|
return output;
|
12
12
|
};
|
@@ -2,38 +2,38 @@ var SumOfMultiples = require('./sum-of-multiples');
|
|
2
2
|
|
3
3
|
describe('SumOfMultiples', function () {
|
4
4
|
it('to 1', function () {
|
5
|
-
expect(SumOfMultiples([3, 5]).to(1)).toBe(0);
|
5
|
+
expect(new SumOfMultiples([3, 5]).to(1)).toBe(0);
|
6
6
|
});
|
7
7
|
|
8
8
|
xit('to 3', function () {
|
9
|
-
expect(SumOfMultiples([3, 5]).to(4)).toBe(3);
|
9
|
+
expect(new SumOfMultiples([3, 5]).to(4)).toBe(3);
|
10
10
|
});
|
11
11
|
|
12
12
|
xit('to 10', function () {
|
13
|
-
expect(SumOfMultiples([3, 5]).to(10)).toBe(23);
|
13
|
+
expect(new SumOfMultiples([3, 5]).to(10)).toBe(23);
|
14
14
|
});
|
15
15
|
|
16
16
|
xit('to 100', function () {
|
17
|
-
expect(SumOfMultiples([3, 5]).to(100)).toBe(2318);
|
17
|
+
expect(new SumOfMultiples([3, 5]).to(100)).toBe(2318);
|
18
18
|
});
|
19
19
|
|
20
20
|
xit('to 1000', function () {
|
21
|
-
expect(SumOfMultiples([3, 5]).to(1000)).toBe(233168);
|
21
|
+
expect(new SumOfMultiples([3, 5]).to(1000)).toBe(233168);
|
22
22
|
});
|
23
23
|
|
24
24
|
xit('[7, 13, 17] to 20', function () {
|
25
|
-
expect(SumOfMultiples([7, 13, 17]).to(20)).toBe(51);
|
25
|
+
expect(new SumOfMultiples([7, 13, 17]).to(20)).toBe(51);
|
26
26
|
});
|
27
27
|
|
28
28
|
xit('[4, 6] to 15', function () {
|
29
|
-
expect(SumOfMultiples([4, 6]).to(15)).toBe(30);
|
29
|
+
expect(new SumOfMultiples([4, 6]).to(15)).toBe(30);
|
30
30
|
});
|
31
31
|
|
32
32
|
xit('[5, 6, 8] to 150', function () {
|
33
|
-
expect(SumOfMultiples([5, 6, 8]).to(150)).toBe(4419);
|
33
|
+
expect(new SumOfMultiples([5, 6, 8]).to(150)).toBe(4419);
|
34
34
|
});
|
35
35
|
|
36
36
|
xit('[43, 47] to 10000', function () {
|
37
|
-
expect(SumOfMultiples([43, 47]).to(10000)).toBe(2203160);
|
37
|
+
expect(new SumOfMultiples([43, 47]).to(10000)).toBe(2203160);
|
38
38
|
});
|
39
39
|
});
|
data/tracks/python/config.json
CHANGED
@@ -1116,17 +1116,39 @@
|
|
1116
1116
|
]
|
1117
1117
|
},
|
1118
1118
|
{
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1119
|
+
"uuid": "4354f631-0cf5-9980-75e7-86d1c3da1f0d3f5e619",
|
1120
|
+
"slug": "dominoes",
|
1121
|
+
"core": false,
|
1122
|
+
"unlocked_by": null,
|
1123
|
+
"difficulty": 7,
|
1124
|
+
"topics": [
|
1125
|
+
"tuples",
|
1126
|
+
"lists"
|
1127
|
+
]
|
1128
|
+
},
|
1129
|
+
{
|
1130
|
+
"uuid": "55c818d6-04a8-2480-de83-9f85fd0d2eafa71935f",
|
1131
|
+
"slug": "pov",
|
1132
|
+
"core": false,
|
1133
|
+
"unlocked_by": null,
|
1134
|
+
"difficulty": 9,
|
1135
|
+
"topics": [
|
1136
|
+
"graphs",
|
1137
|
+
"recursion",
|
1138
|
+
"searching",
|
1139
|
+
"trees"
|
1140
|
+
]
|
1141
|
+
},
|
1142
|
+
{
|
1143
|
+
"uuid": "21dacf48-0580-4d80-a6d2-257b07ad3cc47b02454",
|
1144
|
+
"slug": "react",
|
1145
|
+
"core": false,
|
1146
|
+
"unlocked_by": null,
|
1147
|
+
"difficulty": 8,
|
1148
|
+
"topics": [
|
1149
|
+
"events",
|
1150
|
+
"reactive_programming"
|
1151
|
+
]
|
1130
1152
|
},
|
1131
1153
|
{
|
1132
1154
|
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Dominoes
|
2
|
+
|
3
|
+
Make a chain of dominoes.
|
4
|
+
|
5
|
+
Compute a way to order a given set of dominoes in such a way that they form a
|
6
|
+
correct domino chain (the dots on one half of a stone match the dots on the
|
7
|
+
neighbouring half of an adjacent stone) and that dots on the halfs of the stones
|
8
|
+
which don't have a neighbour (the first and last stone) match each other.
|
9
|
+
|
10
|
+
For example given the stones `[2|1]`, `[2|3]` and `[1|3]` you should compute something
|
11
|
+
like `[1|2] [2|3] [3|1]` or `[3|2] [2|1] [1|3]` or `[1|3] [3|2] [2|1]` etc, where the first and last numbers are the same.
|
12
|
+
|
13
|
+
For stones `[1|2]`, `[4|1]` and `[2|3]` the resulting chain is not valid: `[4|1] [1|2] [2|3]`'s first and last numbers are not the same. 4 != 3
|
14
|
+
|
15
|
+
Some test cases may use duplicate stones in a chain solution, assume that multiple Domino sets are being used.
|
16
|
+
|
17
|
+
## Submitting Exercises
|
18
|
+
|
19
|
+
Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
|
20
|
+
|
21
|
+
For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/python/bob/bob.py`.
|
22
|
+
|
23
|
+
|
24
|
+
For more detailed information about running tests, code style and linting,
|
25
|
+
please see the [help page](http://exercism.io/languages/python).
|
26
|
+
|
27
|
+
## Submitting Incomplete Solutions
|
28
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
@@ -0,0 +1,114 @@
|
|
1
|
+
import unittest
|
2
|
+
|
3
|
+
from dominoes import chain
|
4
|
+
|
5
|
+
|
6
|
+
# Tests adapted from `problem-specifications//canonical-data.json` @ v2.0.0
|
7
|
+
|
8
|
+
class DominoesTest(unittest.TestCase):
|
9
|
+
def test_empty_input_empty_output(self):
|
10
|
+
input_dominoes = []
|
11
|
+
output_chain = chain(input_dominoes)
|
12
|
+
self.assert_correct_chain(input_dominoes, output_chain)
|
13
|
+
|
14
|
+
def test_singleton_input_singleton_output(self):
|
15
|
+
input_dominoes = [(1, 1)]
|
16
|
+
output_chain = chain(input_dominoes)
|
17
|
+
self.assert_correct_chain(input_dominoes, output_chain)
|
18
|
+
|
19
|
+
def test_singleton_cant_be_chained(self):
|
20
|
+
input_dominoes = [(1, 2)]
|
21
|
+
output_chain = chain(input_dominoes)
|
22
|
+
self.refute_correct_chain(input_dominoes, output_chain)
|
23
|
+
|
24
|
+
def test_three_elements(self):
|
25
|
+
input_dominoes = [(1, 2), (3, 1), (2, 3)]
|
26
|
+
output_chain = chain(input_dominoes)
|
27
|
+
self.assert_correct_chain(input_dominoes, output_chain)
|
28
|
+
|
29
|
+
def test_can_reverse_dominoes(self):
|
30
|
+
input_dominoes = [(1, 2), (1, 3), (2, 3)]
|
31
|
+
output_chain = chain(input_dominoes)
|
32
|
+
self.assert_correct_chain(input_dominoes, output_chain)
|
33
|
+
|
34
|
+
def test_cant_be_chained(self):
|
35
|
+
input_dominoes = [(1, 2), (4, 1), (2, 3)]
|
36
|
+
output_chain = chain(input_dominoes)
|
37
|
+
self.refute_correct_chain(input_dominoes, output_chain)
|
38
|
+
|
39
|
+
def test_disconnected_simple(self):
|
40
|
+
input_dominoes = [(1, 1), (2, 2)]
|
41
|
+
output_chain = chain(input_dominoes)
|
42
|
+
self.refute_correct_chain(input_dominoes, output_chain)
|
43
|
+
|
44
|
+
def test_disconnected_double_loop(self):
|
45
|
+
input_dominoes = [(1, 2), (2, 1), (3, 4), (4, 3)]
|
46
|
+
output_chain = chain(input_dominoes)
|
47
|
+
self.refute_correct_chain(input_dominoes, output_chain)
|
48
|
+
|
49
|
+
def test_disconnected_single_isolated(self):
|
50
|
+
input_dominoes = [(1, 2), (2, 3), (3, 1), (4, 4)]
|
51
|
+
output_chain = chain(input_dominoes)
|
52
|
+
self.refute_correct_chain(input_dominoes, output_chain)
|
53
|
+
|
54
|
+
def test_need_backtrack(self):
|
55
|
+
input_dominoes = [(1, 2), (2, 3), (3, 1), (2, 4), (2, 4)]
|
56
|
+
output_chain = chain(input_dominoes)
|
57
|
+
self.assert_correct_chain(input_dominoes, output_chain)
|
58
|
+
|
59
|
+
def test_separate_loops(self):
|
60
|
+
input_dominoes = [(1, 2), (2, 3), (3, 1), (1, 1), (2, 2), (3, 3)]
|
61
|
+
output_chain = chain(input_dominoes)
|
62
|
+
self.assert_correct_chain(input_dominoes, output_chain)
|
63
|
+
|
64
|
+
def test_nine_elements(self):
|
65
|
+
input_dominoes = [(1, 2), (5, 3), (3, 1), (1, 2), (2, 4), (1, 6),
|
66
|
+
(2, 3), (3, 4), (5, 6)]
|
67
|
+
output_chain = chain(input_dominoes)
|
68
|
+
self.assert_correct_chain(input_dominoes, output_chain)
|
69
|
+
|
70
|
+
# Utility methods
|
71
|
+
|
72
|
+
def normalize_dominoes(self, dominoes):
|
73
|
+
return list(sorted(tuple(sorted(domino)) for domino in dominoes))
|
74
|
+
|
75
|
+
def assert_same_dominoes(self, input_dominoes, output_chain):
|
76
|
+
msg = ('Dominoes used in the output must be the same '
|
77
|
+
'as the ones given in the input')
|
78
|
+
input_normal = self.normalize_dominoes(input_dominoes)
|
79
|
+
output_normal = self.normalize_dominoes(output_chain)
|
80
|
+
self.assertEqual(input_normal, output_normal, msg)
|
81
|
+
|
82
|
+
def assert_consecutive_dominoes_match(self, output_chain):
|
83
|
+
for i in range(len(output_chain) - 1):
|
84
|
+
msg = ("In chain {}, right end of domino {} ({}) "
|
85
|
+
"and left end of domino {} ({}) must match")
|
86
|
+
msg = msg.format(output_chain,
|
87
|
+
i,
|
88
|
+
output_chain[i],
|
89
|
+
i + 1,
|
90
|
+
output_chain[i + 1])
|
91
|
+
self.assertEqual(output_chain[i][1], output_chain[i + 1][0], msg)
|
92
|
+
|
93
|
+
def assert_dominoes_at_ends_match(self, output_chain):
|
94
|
+
msg = ("In chain {}, left end of first domino ({}) and "
|
95
|
+
"right end of last domino ({}) must match")
|
96
|
+
msg = msg.format(output_chain, output_chain[0], output_chain[-1])
|
97
|
+
self.assertEqual(output_chain[0][0], output_chain[-1][1], msg)
|
98
|
+
|
99
|
+
def assert_correct_chain(self, input_dominoes, output_chain):
|
100
|
+
msg = 'There should be a chain for {}'.format(input_dominoes)
|
101
|
+
self.assertIsNotNone(output_chain, msg)
|
102
|
+
self.assert_same_dominoes(input_dominoes, output_chain)
|
103
|
+
if not any(output_chain):
|
104
|
+
return
|
105
|
+
self.assert_consecutive_dominoes_match(output_chain)
|
106
|
+
self.assert_dominoes_at_ends_match(output_chain)
|
107
|
+
|
108
|
+
def refute_correct_chain(self, input_dominoes, output_chain):
|
109
|
+
msg = 'There should be no valid chain for {}'.format(input_dominoes)
|
110
|
+
self.assertIsNone(output_chain, msg)
|
111
|
+
|
112
|
+
|
113
|
+
if __name__ == '__main__':
|
114
|
+
unittest.main()
|
@@ -0,0 +1,30 @@
|
|
1
|
+
from itertools import permutations
|
2
|
+
from functools import reduce
|
3
|
+
|
4
|
+
|
5
|
+
def swap(a, b):
|
6
|
+
return (b, a)
|
7
|
+
|
8
|
+
|
9
|
+
def build_chain(chain, domino):
|
10
|
+
if chain is not None:
|
11
|
+
last = chain[-1]
|
12
|
+
if len(chain) == 1 and last[0] == domino[0]:
|
13
|
+
return [swap(*last), domino]
|
14
|
+
elif len(chain) == 1 and last[0] == domino[1]:
|
15
|
+
return [swap(*last), swap(*domino)]
|
16
|
+
elif last[1] == domino[0]:
|
17
|
+
return chain + [domino]
|
18
|
+
elif last[1] == domino[1]:
|
19
|
+
return chain + [swap(*domino)]
|
20
|
+
return None
|
21
|
+
|
22
|
+
|
23
|
+
def chain(dominoes):
|
24
|
+
if not any(dominoes):
|
25
|
+
return []
|
26
|
+
for perm in permutations(dominoes):
|
27
|
+
chain = reduce(build_chain, perm[1:], [perm[0]])
|
28
|
+
if chain is not None and chain[0][0] == chain[-1][1]:
|
29
|
+
return chain
|
30
|
+
return None
|
@@ -6,34 +6,29 @@ from grains import (
|
|
6
6
|
)
|
7
7
|
|
8
8
|
|
9
|
+
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0
|
10
|
+
|
9
11
|
class GrainsTest(unittest.TestCase):
|
10
12
|
def test_square_1(self):
|
11
13
|
self.assertEqual(on_square(1), 1)
|
12
|
-
self.assertEqual(total_after(1), 1)
|
13
14
|
|
14
15
|
def test_square_2(self):
|
15
16
|
self.assertEqual(on_square(2), 2)
|
16
|
-
self.assertEqual(total_after(2), 3)
|
17
17
|
|
18
18
|
def test_square_3(self):
|
19
19
|
self.assertEqual(on_square(3), 4)
|
20
|
-
self.assertEqual(total_after(3), 7)
|
21
20
|
|
22
21
|
def test_square_4(self):
|
23
22
|
self.assertEqual(on_square(4), 8)
|
24
|
-
self.assertEqual(total_after(4), 15)
|
25
23
|
|
26
24
|
def test_square_16(self):
|
27
25
|
self.assertEqual(on_square(16), 32768)
|
28
|
-
self.assertEqual(total_after(16), 65535)
|
29
26
|
|
30
27
|
def test_square_32(self):
|
31
28
|
self.assertEqual(on_square(32), 2147483648)
|
32
|
-
self.assertEqual(total_after(32), 4294967295)
|
33
29
|
|
34
30
|
def test_square_64(self):
|
35
31
|
self.assertEqual(on_square(64), 9223372036854775808)
|
36
|
-
self.assertEqual(total_after(64), 18446744073709551615)
|
37
32
|
|
38
33
|
def test_square_0_raises_exception(self):
|
39
34
|
with self.assertRaises(ValueError):
|
@@ -53,6 +48,9 @@ class GrainsTest(unittest.TestCase):
|
|
53
48
|
with self.assertRaises(ValueError):
|
54
49
|
total_after(65)
|
55
50
|
|
51
|
+
def test_total(self):
|
52
|
+
self.assertEqual(total_after(64), 18446744073709551615)
|
53
|
+
|
56
54
|
|
57
55
|
if __name__ == '__main__':
|
58
56
|
unittest.main()
|
@@ -4,21 +4,15 @@ import re
|
|
4
4
|
class Phone(object):
|
5
5
|
def __init__(self, number):
|
6
6
|
self.number = self._clean(number)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def exchange_code(self):
|
12
|
-
return self.number[3:6]
|
13
|
-
|
14
|
-
def subscriber_number(self):
|
15
|
-
return self.number[-4:]
|
7
|
+
self.area_code = self.number[:3]
|
8
|
+
self.exchange_code = self.number[3:6]
|
9
|
+
self.subscriber_number = self.number[-4:]
|
16
10
|
|
17
11
|
def pretty(self):
|
18
12
|
return "(%s) %s-%s" % (
|
19
|
-
self.area_code
|
20
|
-
self.exchange_code
|
21
|
-
self.subscriber_number
|
13
|
+
self.area_code,
|
14
|
+
self.exchange_code,
|
15
|
+
self.subscriber_number
|
22
16
|
)
|
23
17
|
|
24
18
|
def _clean(self, number):
|
@@ -35,4 +29,4 @@ class Phone(object):
|
|
35
29
|
if valid:
|
36
30
|
return number[-10:]
|
37
31
|
else:
|
38
|
-
|
32
|
+
raise ValueError()
|
@@ -19,12 +19,12 @@ class PhoneTest(unittest.TestCase):
|
|
19
19
|
self.assertEqual(number, "2234567890")
|
20
20
|
|
21
21
|
def test_invalid_when_9_digits(self):
|
22
|
-
|
23
|
-
|
22
|
+
with self.assertRaises(ValueError):
|
23
|
+
Phone("123456789")
|
24
24
|
|
25
25
|
def test_invalid_when_11_digits_and_first_not_1(self):
|
26
|
-
|
27
|
-
|
26
|
+
with self.assertRaises(ValueError):
|
27
|
+
Phone("22234567890")
|
28
28
|
|
29
29
|
def test_valid_when_11_digits_and_first_is_1(self):
|
30
30
|
number = Phone("12234567890").number
|
@@ -35,29 +35,29 @@ class PhoneTest(unittest.TestCase):
|
|
35
35
|
self.assertEqual(number, "2234567890")
|
36
36
|
|
37
37
|
def test_invalid_when_more_than_11_digits(self):
|
38
|
-
|
39
|
-
|
38
|
+
with self.assertRaises(ValueError):
|
39
|
+
Phone("321234567890")
|
40
40
|
|
41
41
|
def test_invalid_with_letters(self):
|
42
|
-
|
43
|
-
|
42
|
+
with self.assertRaises(ValueError):
|
43
|
+
Phone("123-abc-7890")
|
44
44
|
|
45
45
|
def test_invalid_with_punctuation(self):
|
46
|
-
|
47
|
-
|
46
|
+
with self.assertRaises(ValueError):
|
47
|
+
Phone("123-@:!-7890")
|
48
48
|
|
49
49
|
def test_invalid_area_code(self):
|
50
|
-
|
51
|
-
|
50
|
+
with self.assertRaises(ValueError):
|
51
|
+
Phone("(123) 456-7890")
|
52
52
|
|
53
53
|
def test_invalid_exchange_code(self):
|
54
|
-
|
55
|
-
|
54
|
+
with self.assertRaises(ValueError):
|
55
|
+
Phone("(223) 056-7890")
|
56
56
|
|
57
57
|
# Track specific tests
|
58
58
|
def test_area_code(self):
|
59
59
|
number = Phone("2234567890")
|
60
|
-
self.assertEqual(number.area_code
|
60
|
+
self.assertEqual(number.area_code, "223")
|
61
61
|
|
62
62
|
def test_pretty_print(self):
|
63
63
|
number = Phone("2234567890")
|
@@ -3,81 +3,120 @@ import unittest
|
|
3
3
|
from poker import poker
|
4
4
|
|
5
5
|
|
6
|
+
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0
|
7
|
+
|
6
8
|
class PokerTest(unittest.TestCase):
|
7
|
-
def
|
9
|
+
def test_single_hand_wins(self):
|
8
10
|
hand = '4S 5S 7H 8D JC'.split()
|
9
11
|
self.assertEqual(poker([hand]), [hand])
|
10
12
|
|
11
|
-
def
|
12
|
-
|
13
|
+
def highest_card_wins(self):
|
14
|
+
first = '4D 5S 6S 8D 3C'.split()
|
15
|
+
second = '2S 4C 7S 9H 10H'.split()
|
16
|
+
third = '3S 4S 5D 6H JH'.split()
|
17
|
+
self.assertEqual(poker([first, second, third]), [third])
|
18
|
+
|
19
|
+
def tie_has_multiple_winners(self):
|
20
|
+
first = '4D 5S 6S 8D 3C'.split()
|
21
|
+
second = '2S 4C 7S 9H 10H'.split()
|
22
|
+
third = '3S 4S 5D 6H JH'.split()
|
23
|
+
fourth = '3H 4H 5C 6C JD'.split()
|
24
|
+
self.assertEqual(
|
25
|
+
poker([first, second, third, fourth]),
|
26
|
+
[third, fourth])
|
27
|
+
|
28
|
+
def tie_compares_multiple(self):
|
29
|
+
higher = '3S 5H 6S 8D 7H'.split()
|
30
|
+
lower = '2S 5D 6D 8C 7S'.split()
|
31
|
+
self.assertEqual(poker([higher, lower]), [higher])
|
32
|
+
|
33
|
+
def pair_beats_high_card(self):
|
34
|
+
nothing = '4S 5H 6C 8D KH'.split()
|
13
35
|
pairOf4 = '2S 4H 6S 4D JH'.split()
|
14
36
|
self.assertEqual(poker([nothing, pairOf4]), [pairOf4])
|
15
37
|
|
16
|
-
def
|
38
|
+
def highest_pair_wins(self):
|
17
39
|
pairOf2 = '4S 2H 6S 2D JH'.split()
|
18
|
-
pairOf4 = '2S 4H
|
40
|
+
pairOf4 = '2S 4H 6C 4D JD'.split()
|
19
41
|
self.assertEqual(poker([pairOf2, pairOf4]), [pairOf4])
|
20
42
|
|
21
|
-
def
|
43
|
+
def two_pairs_beats_one_pair(self):
|
22
44
|
pairOf8 = '2S 8H 6S 8D JH'.split()
|
23
|
-
doublePair = '4S 5H
|
45
|
+
doublePair = '4S 5H 4C 8C 5C'.split()
|
24
46
|
self.assertEqual(poker([pairOf8, doublePair]), [doublePair])
|
25
47
|
|
26
48
|
def test_two_double_pair(self):
|
27
|
-
doublePair2and8 = '2S 8H
|
28
|
-
doublePair4and5 = '4S 5H
|
49
|
+
doublePair2and8 = '2S 8H 2D 8D 3H'.split()
|
50
|
+
doublePair4and5 = '4S 5H 4C 8S 5D'.split()
|
29
51
|
self.assertEqual(
|
30
52
|
poker([doublePair2and8, doublePair4and5]), [doublePair2and8])
|
31
53
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
54
|
+
def test_two_double_pair_higher_tie(self):
|
55
|
+
doublePair2andQ = '2S QS 2C QD JH'.split()
|
56
|
+
doublePairJandQ = 'JD QH JS 8D QC'.split()
|
35
57
|
self.assertEqual(
|
36
|
-
poker([
|
58
|
+
poker([doublePair2andQ, doublePairJandQ]), [doublePairJandQ])
|
37
59
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
60
|
+
def test_two_double_pair_tie_kicker(self):
|
61
|
+
doublePair2and8high = 'JD QH JS 8D QC'.split()
|
62
|
+
doublePair2and8 = 'JS QS JC 2D QD'.split()
|
41
63
|
self.assertEqual(
|
42
64
|
poker([doublePair2and8high, doublePair2and8]),
|
43
65
|
[doublePair2and8high])
|
44
66
|
|
45
|
-
def
|
46
|
-
doublePair2and8 = '2S 8H
|
47
|
-
threeOf4 = '4S 5H
|
67
|
+
def three_beats_two_pair(self):
|
68
|
+
doublePair2and8 = '2S 8H 2H 8D JH'.split()
|
69
|
+
threeOf4 = '4S 5H 4C 8S 4H'.split()
|
48
70
|
self.assertEqual(poker([doublePair2and8, threeOf4]), [threeOf4])
|
49
71
|
|
50
72
|
def test_two_three(self):
|
51
|
-
threeOf2 = '2S 2H
|
52
|
-
threeOf1 = '4S AH AS
|
73
|
+
threeOf2 = '2S 2H 2C 8D JH'.split()
|
74
|
+
threeOf1 = '4S AH AS 8C AD'.split()
|
53
75
|
self.assertEqual(poker([threeOf2, threeOf1]), [threeOf1])
|
54
76
|
|
77
|
+
def test_two_three_multiple_decks(self):
|
78
|
+
threeOf1Low = '4S AH AS 7C AD'.split()
|
79
|
+
threeOf1High = '4S AH AS 8C AD'.split()
|
80
|
+
self.assertEqual(poker([threeOf1Low, threeOf1High]), [threeOf1High])
|
81
|
+
|
55
82
|
def test_three_vs_straight(self):
|
56
|
-
threeOf4 = '4S 5H
|
57
|
-
straight = '3S
|
83
|
+
threeOf4 = '4S 5H 4C 8D 4H'.split()
|
84
|
+
straight = '3S 4D 2S 6D 5C'.split()
|
85
|
+
self.assertEqual(poker([threeOf4, straight]), [straight])
|
86
|
+
|
87
|
+
def aces_can_end_straight(self):
|
88
|
+
threeOf4 = '4S 5H 4C 8D 4H'.split()
|
89
|
+
straight = '10D JH QS KD AC'.split()
|
90
|
+
self.assertEqual(poker([threeOf4, straight]), [straight])
|
91
|
+
|
92
|
+
def aces_can_start_straight(self):
|
93
|
+
threeOf4 = '4S 5H 4C 8D 4H'.split()
|
94
|
+
straight = '4D AH 3S 2D 5C'.split()
|
58
95
|
self.assertEqual(poker([threeOf4, straight]), [straight])
|
59
96
|
|
60
97
|
def test_two_straights(self):
|
61
|
-
straightTo8 = '4S
|
98
|
+
straightTo8 = '4S 6C 7S 8D 5H'.split()
|
62
99
|
straightTo9 = '5S 7H 8S 9D 6H'.split()
|
63
100
|
self.assertEqual(poker([straightTo8, straightTo9]), [straightTo9])
|
64
|
-
|
101
|
+
|
102
|
+
def test_two_straights_lowest(self):
|
103
|
+
straightTo6 = '2H 3C 4D 5D 6H'.split()
|
65
104
|
straightTo5 = '4S AH 3S 2D 5H'.split()
|
66
|
-
self.assertEqual(poker([
|
105
|
+
self.assertEqual(poker([straightTo6, straightTo5]), [straightTo6])
|
67
106
|
|
68
107
|
def test_straight_vs_flush(self):
|
69
|
-
straightTo8 = '
|
108
|
+
straightTo8 = '4C 6H 7D 8D 5H'.split()
|
70
109
|
flushTo7 = '2S 4S 5S 6S 7S'.split()
|
71
110
|
self.assertEqual(poker([straightTo8, flushTo7]), [flushTo7])
|
72
111
|
|
73
112
|
def test_two_flushes(self):
|
74
|
-
|
113
|
+
flushTo9 = '4H 7H 8H 9H 6H'.split()
|
75
114
|
flushTo7 = '2S 4S 5S 6S 7S'.split()
|
76
|
-
self.assertEqual(poker([
|
115
|
+
self.assertEqual(poker([flushTo9, flushTo7]), [flushTo9])
|
77
116
|
|
78
117
|
def test_flush_vs_full(self):
|
79
118
|
flushTo8 = '3H 6H 7H 8H 5H'.split()
|
80
|
-
full = '4S 5H
|
119
|
+
full = '4S 5H 4C 5D 4H'.split()
|
81
120
|
self.assertEqual(poker([full, flushTo8]), [full])
|
82
121
|
|
83
122
|
def test_two_fulls(self):
|
@@ -85,21 +124,31 @@ class PokerTest(unittest.TestCase):
|
|
85
124
|
fullOf5by8 = '5H 5S 5D 8S 8D'.split()
|
86
125
|
self.assertEqual(poker([fullOf4by9, fullOf5by8]), [fullOf5by8])
|
87
126
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
91
|
-
self.assertEqual(poker([
|
92
|
-
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
self.assertEqual(poker([
|
97
|
-
|
98
|
-
def
|
99
|
-
|
100
|
-
|
127
|
+
def test_two_fulls_same_triplet(self):
|
128
|
+
fullOf5by9 = '5H 5S 5D 9S 9D'.split()
|
129
|
+
fullOf5by8 = '5H 5S 5D 8S 8D'.split()
|
130
|
+
self.assertEqual(poker([fullOf5by9, fullOf5by8]), [fullOf5by9])
|
131
|
+
|
132
|
+
def test_full_vs_four(self):
|
133
|
+
full = '4S 5H 4D 5D 4H'.split()
|
134
|
+
fourOf3 = '3S 3H 2S 3D 3C'.split()
|
135
|
+
self.assertEqual(poker([full, fourOf3]), [fourOf3])
|
136
|
+
|
137
|
+
def test_two_fours(self):
|
138
|
+
fourOf2 = '2S 2H 2C 8D 2D'.split()
|
139
|
+
fourOf5 = '4S 5H 5S 5D 5C'.split()
|
140
|
+
self.assertEqual(poker([fourOf2, fourOf5]), [fourOf5])
|
141
|
+
|
142
|
+
def test_two_fours_kicker(self):
|
143
|
+
fourOf3low = '3S 3H 2S 3D 3C'.split()
|
144
|
+
fourOf3high = '3S 3H 4S 3D 3C'.split()
|
145
|
+
self.assertEqual(poker([fourOf3low, fourOf3high]), [fourOf3high])
|
146
|
+
|
147
|
+
def test_four_vs_straight_flush(self):
|
148
|
+
fourOf5 = '4S 5H 5S 5D 5C'.split()
|
149
|
+
straightFlushTo9 = '7S 8S 9S 6S 5S'.split()
|
101
150
|
self.assertEqual(
|
102
|
-
poker([
|
151
|
+
poker([fourOf5, straightFlushTo9]), [straightFlushTo9])
|
103
152
|
|
104
153
|
def test_two_straight_flushes(self):
|
105
154
|
straightFlushTo8 = '4H 6H 7H 8H 5H'.split()
|
@@ -107,14 +156,6 @@ class PokerTest(unittest.TestCase):
|
|
107
156
|
self.assertEqual(
|
108
157
|
poker([straightFlushTo8, straightFlushTo9]), [straightFlushTo9])
|
109
158
|
|
110
|
-
def test_three_hand_with_tie(self):
|
111
|
-
spadeStraightTo9 = '9S 8S 7S 6S 5S'.split()
|
112
|
-
diamondStraightTo9 = '9D 8D 7D 6D 5D'.split()
|
113
|
-
threeOf4 = '4D 4S 4H QS KS'.split()
|
114
|
-
self.assertEqual(
|
115
|
-
poker([spadeStraightTo9, diamondStraightTo9, threeOf4]),
|
116
|
-
[spadeStraightTo9, diamondStraightTo9])
|
117
|
-
|
118
159
|
|
119
160
|
if __name__ == '__main__':
|
120
161
|
unittest.main()
|