Skip to content

Commit 0f52f8c

Browse files
mrcfpscmccandless
authored andcommitted
queen-attack: re-implement according to canonical data 2.1.0 (#1351)
* queen-attack: re-implement according to canonical data 2.1.0 * queen-attack: rewrite to pass tests v2.1.0 * queen-attack: remove redundant tests Rm `test_invalid_position_can_attack` since `Queen()`
1 parent 875a78a commit 0f52f8c

File tree

3 files changed

+39
-80
lines changed

3 files changed

+39
-80
lines changed

exercises/queen-attack/example.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,17 @@
1-
def board(pos1, pos2):
2-
validate_position(pos1, pos2)
3-
x1, y1 = pos1
4-
x2, y2 = pos2
5-
b = [['_'] * 8 for i in range(8)]
6-
b[x1][y1] = 'W'
7-
b[x2][y2] = 'B'
8-
return [''.join(r) for r in b]
1+
class Queen(object):
2+
def __init__(self, row, column):
3+
if not 0 <= row <= 7 or not 0 <= column <= 7:
4+
raise ValueError("Invalid queen position: queen out of the board")
5+
self.row = row
6+
self.column = column
97

10-
11-
def can_attack(pos1, pos2):
12-
validate_position(pos1, pos2)
13-
x1, y1 = pos1
14-
x2, y2 = pos2
15-
dx = x1 - x2 if x1 >= x2 else x2 - x1
16-
dy = y1 - y2 if y1 >= y2 else y2 - y1
17-
if dx == dy or dx == 0 or dy == 0:
18-
return True
19-
return False
20-
21-
22-
def validate_position(pos1, pos2):
23-
if any(x < 0 or x > 7 for x in pos1 + pos2):
24-
raise ValueError('Invalid queen position: queen out of the board')
25-
if pos1 == pos2:
26-
raise ValueError('Invalid queen position: both queens in the same '
27-
'square: {0}'.format(pos1))
8+
def can_attack(self, another_queen):
9+
dx = abs(self.row - another_queen.row)
10+
dy = abs(self.column - another_queen.column)
11+
if dx == dy == 0:
12+
raise ValueError(
13+
'Invalid queen position: both queens in the same square')
14+
elif dx == dy or dx == 0 or dy == 0:
15+
return True
16+
else:
17+
return False
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
def board(white_position, black_position):
2-
pass
1+
class Queen(object):
2+
def __init__(self, row, column):
3+
pass
34

4-
5-
def can_attack(white_position, black_position):
6-
pass
5+
def can_attack(self, another_queen):
6+
pass

exercises/queen-attack/queen_attack_test.py

Lines changed: 18 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,61 @@
11
import unittest
22

3-
from queen_attack import board, can_attack
3+
from queen_attack import Queen
44

55

6-
# Tests adapted from `problem-specifications//canonical-data.json` @ v2.0.0
6+
# Tests adapted from `problem-specifications//canonical-data.json` @ v2.1.0
77

88
class QueenAttackTest(unittest.TestCase):
99

10+
# Test creation of Queens with valid and invalid positions
1011
def test_queen_valid_position(self):
1112
try:
12-
board((1, 1), (2, 2))
13+
Queen(2, 2)
1314
except ValueError:
1415
self.fail("Unexpected Exception")
1516

1617
def test_queen_negative_row(self):
1718
with self.assertRaisesWithMessage(ValueError):
18-
board((1, 1), (-2, 2))
19+
Queen(-2, 2)
1920

2021
def test_queen_invalid_row(self):
2122
with self.assertRaisesWithMessage(ValueError):
22-
board((1, 1), (8, 4))
23+
Queen(8, 4)
2324

2425
def test_queen_negative_column(self):
2526
with self.assertRaisesWithMessage(ValueError):
26-
board((1, 1), (2, -2))
27+
Queen(2, -2)
2728

2829
def test_queen_invalid_column(self):
2930
with self.assertRaisesWithMessage(ValueError):
30-
board((1, 1), (4, 8))
31+
Queen(4, 8)
3132

33+
# Test the ability of one queen to attack another
3234
def test_attack_false(self):
33-
self.assertIs(can_attack((2, 4), (6, 6)), False)
35+
self.assertIs(Queen(2, 4).can_attack(Queen(6, 6)), False)
3436

3537
def test_attack_same_row(self):
36-
self.assertIs(can_attack((2, 4), (2, 6)), True)
38+
self.assertIs(Queen(2, 4).can_attack(Queen(2, 6)), True)
3739

3840
def test_attack_same_column(self):
39-
self.assertIs(can_attack((4, 5), (2, 5)), True)
41+
self.assertIs(Queen(4, 5).can_attack(Queen(2, 5)), True)
4042

4143
def test_attack_diagonal1(self):
42-
self.assertIs(can_attack((2, 2), (0, 4)), True)
44+
self.assertIs(Queen(2, 2).can_attack(Queen(0, 4)), True)
4345

4446
def test_attack_diagonal2(self):
45-
self.assertIs(can_attack((2, 2), (3, 1)), True)
47+
self.assertIs(Queen(2, 2).can_attack(Queen(3, 1)), True)
4648

4749
def test_attack_diagonal3(self):
48-
self.assertIs(can_attack((2, 2), (1, 1)), True)
50+
self.assertIs(Queen(2, 2).can_attack(Queen(1, 1)), True)
4951

5052
def test_attack_diagonal4(self):
51-
self.assertIs(can_attack((2, 2), (5, 5)), True)
52-
53-
# Tests beyond this point are not part of the canonical data.
54-
55-
# If either board or can_attack are called with an invalid board position
56-
# they should raise a ValueError with a meaningful error message.
57-
def test_invalid_position_can_attack(self):
58-
with self.assertRaisesWithMessage(ValueError):
59-
can_attack((0, 0), (7, 8))
60-
61-
def test_queens_same_position_board(self):
62-
with self.assertRaisesWithMessage(ValueError):
63-
board((2, 2), (2, 2))
53+
self.assertIs(Queen(2, 2).can_attack(Queen(5, 5)), True)
6454

55+
# Track-specific tests
6556
def test_queens_same_position_can_attack(self):
6657
with self.assertRaisesWithMessage(ValueError):
67-
can_attack((2, 2), (2, 2))
68-
69-
def test_board1(self):
70-
ans = ['________',
71-
'________',
72-
'___W____',
73-
'________',
74-
'________',
75-
'______B_',
76-
'________',
77-
'________']
78-
self.assertEqual(board((2, 3), (5, 6)), ans)
79-
80-
def test_board2(self):
81-
ans = ['______W_',
82-
'_______B',
83-
'________',
84-
'________',
85-
'________',
86-
'________',
87-
'________',
88-
'________']
89-
self.assertEqual(board((0, 6), (1, 7)), ans)
58+
Queen(2, 2).can_attack(Queen(2, 2))
9059

9160
# Utility functions
9261
def setUp(self):

0 commit comments

Comments
 (0)