forked from reingart/exercism
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathdominoes_test.py
132 lines (109 loc) · 4.98 KB
/
dominoes_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/dominoes/canonical-data.json
# File last updated on 2023-07-19
import unittest
from dominoes import (
can_chain,
)
class DominoesTest(unittest.TestCase):
def test_empty_input_empty_output(self):
input_dominoes = []
output_chain = can_chain(input_dominoes)
self.assert_correct_chain(input_dominoes, output_chain)
def test_singleton_input_singleton_output(self):
input_dominoes = [(1, 1)]
output_chain = can_chain(input_dominoes)
self.assert_correct_chain(input_dominoes, output_chain)
def test_singleton_that_can_t_be_chained(self):
input_dominoes = [(1, 2)]
output_chain = can_chain(input_dominoes)
self.refute_correct_chain(input_dominoes, output_chain)
def test_three_elements(self):
input_dominoes = [(1, 2), (3, 1), (2, 3)]
output_chain = can_chain(input_dominoes)
self.assert_correct_chain(input_dominoes, output_chain)
def test_can_reverse_dominoes(self):
input_dominoes = [(1, 2), (1, 3), (2, 3)]
output_chain = can_chain(input_dominoes)
self.assert_correct_chain(input_dominoes, output_chain)
def test_can_t_be_chained(self):
input_dominoes = [(1, 2), (4, 1), (2, 3)]
output_chain = can_chain(input_dominoes)
self.refute_correct_chain(input_dominoes, output_chain)
def test_disconnected_simple(self):
input_dominoes = [(1, 1), (2, 2)]
output_chain = can_chain(input_dominoes)
self.refute_correct_chain(input_dominoes, output_chain)
def test_disconnected_double_loop(self):
input_dominoes = [(1, 2), (2, 1), (3, 4), (4, 3)]
output_chain = can_chain(input_dominoes)
self.refute_correct_chain(input_dominoes, output_chain)
def test_disconnected_single_isolated(self):
input_dominoes = [(1, 2), (2, 3), (3, 1), (4, 4)]
output_chain = can_chain(input_dominoes)
self.refute_correct_chain(input_dominoes, output_chain)
def test_need_backtrack(self):
input_dominoes = [(1, 2), (2, 3), (3, 1), (2, 4), (2, 4)]
output_chain = can_chain(input_dominoes)
self.assert_correct_chain(input_dominoes, output_chain)
def test_separate_loops(self):
input_dominoes = [(1, 2), (2, 3), (3, 1), (1, 1), (2, 2), (3, 3)]
output_chain = can_chain(input_dominoes)
self.assert_correct_chain(input_dominoes, output_chain)
def test_nine_elements(self):
input_dominoes = [
(1, 2),
(5, 3),
(3, 1),
(1, 2),
(2, 4),
(1, 6),
(2, 3),
(3, 4),
(5, 6),
]
output_chain = can_chain(input_dominoes)
self.assert_correct_chain(input_dominoes, output_chain)
def test_separate_three_domino_loops(self):
input_dominoes = [(1, 2), (2, 3), (3, 1), (4, 5), (5, 6), (6, 4)]
output_chain = can_chain(input_dominoes)
self.refute_correct_chain(input_dominoes, output_chain)
# Utility methods
def normalize_dominoes(self, dominoes):
return list(sorted(tuple(sorted(domino)) for domino in dominoes))
def assert_same_dominoes(self, input_dominoes, output_chain):
msg = (
"Dominoes used in the output must be the same "
"as the ones given in the input"
)
input_normal = self.normalize_dominoes(input_dominoes)
output_normal = self.normalize_dominoes(output_chain)
self.assertEqual(input_normal, output_normal, msg)
def assert_consecutive_dominoes_match(self, output_chain):
for i in range(len(output_chain) - 1):
msg = (
"In chain {}, right end of domino {} ({}) "
"and left end of domino {} ({}) must match"
)
msg = msg.format(
output_chain, i, output_chain[i], i + 1, output_chain[i + 1]
)
self.assertEqual(output_chain[i][1], output_chain[i + 1][0], msg)
def assert_dominoes_at_ends_match(self, output_chain):
msg = (
"In chain {}, left end of first domino ({}) and "
"right end of last domino ({}) must match"
)
msg = msg.format(output_chain, output_chain[0], output_chain[-1])
self.assertEqual(output_chain[0][0], output_chain[-1][1], msg)
def assert_correct_chain(self, input_dominoes, output_chain):
msg = "There should be a chain for {}".format(input_dominoes)
self.assertIsNotNone(output_chain, msg)
self.assert_same_dominoes(input_dominoes, output_chain)
if not any(output_chain):
return
self.assert_consecutive_dominoes_match(output_chain)
self.assert_dominoes_at_ends_match(output_chain)
def refute_correct_chain(self, input_dominoes, output_chain):
msg = "There should be no valid chain for {}".format(input_dominoes)
self.assertIsNone(output_chain, msg)