Skip to content

Commit a693317

Browse files
yunchihilya-khadykin
authored andcommitted
Add exercise connect to resolve #733
1 parent 4f083db commit a693317

File tree

5 files changed

+241
-0
lines changed

5 files changed

+241
-0
lines changed

config.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,17 @@
10211021
"text_formatting"
10221022
]
10231023
},
1024+
{
1025+
"uuid": "f5503274-ac23-11e7-abc4-cec278b6b50a",
1026+
"slug": "connect",
1027+
"core": false,
1028+
"unlocked_by": null,
1029+
"difficulty": 1,
1030+
"topics": [
1031+
"parsing",
1032+
"transforming"
1033+
]
1034+
},
10241035
{
10251036
"uuid": "33f689ee-1d9c-4908-a71c-f84bff3510df",
10261037
"slug": "collatz-conjecture",

exercises/connect/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Connect
2+
3+
Compute the result for a game of Hex / Polygon.
4+
5+
The abstract boardgame known as
6+
[Hex](https://en.wikipedia.org/wiki/Hex_%28board_game%29) / Polygon /
7+
CON-TAC-TIX is quite simple in rules, though complex in practice. Two players
8+
place stones on a rhombus with hexagonal fields. The player to connect his/her
9+
stones to the opposite side first wins. The four sides of the rhombus are
10+
divided between the two players (i.e. one player gets assigned a side and the
11+
side directly opposite it and the other player gets assigned the two other
12+
sides).
13+
14+
Your goal is to build a program that given a simple representation of a board
15+
computes the winner (or lack thereof). Note that all games need not be "fair".
16+
(For example, players may have mismatched piece counts.)
17+
18+
The boards look like this (with spaces added for readability, which won't be in
19+
the representation passed to your code):
20+
21+
```
22+
. O . X .
23+
. X X O .
24+
O O O X .
25+
. X O X O
26+
X O O O X
27+
```
28+
29+
"Player `O`" plays from top to bottom, "Player `X`" plays from left to right. In
30+
the above example `O` has made a connection from left to right but nobody has
31+
won since `O` didn't connect top and bottom.
32+
33+
### Submitting Exercises
34+
35+
Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
36+
37+
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`.
38+
39+
40+
For more detailed information about running tests, code style and linting,
41+
please see the [help page](http://exercism.io/languages/python).
42+
43+
## Submitting Incomplete Solutions
44+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

exercises/connect/connect.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
class ConnectGame:
3+
def __init__(self, board):
4+
pass
5+
6+
def get_winner(self):
7+
pass

exercises/connect/connect_test.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import unittest
2+
3+
import connect
4+
5+
6+
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0
7+
8+
testcases = [
9+
{
10+
"description": "an empty board has no winner",
11+
"board":
12+
""" . . . . .
13+
. . . . .
14+
. . . . .
15+
. . . . .
16+
. . . . .""",
17+
"winner": ""
18+
},
19+
{
20+
"description": "O can win on a 1x1 board",
21+
"board": "O",
22+
"winner": "O"
23+
},
24+
{
25+
"description": "X can win on a 1x1 board",
26+
"board": "X",
27+
"winner": "X"
28+
},
29+
{
30+
"description": "only edges does not make a winner",
31+
"board":
32+
""" O O O X
33+
X . . X
34+
X . . X
35+
X O O O""",
36+
"winner": ""
37+
},
38+
{
39+
"description": "illegal diagonal does not make a winner",
40+
"board":
41+
""" X O . .
42+
O X X X
43+
O X O .
44+
. O X .
45+
X X O O""",
46+
"winner": ""
47+
},
48+
{
49+
"description": "nobody wins crossing adjacent angles",
50+
"board":
51+
""" X . . .
52+
. X O .
53+
O . X O
54+
. O . X
55+
. . O .""",
56+
"winner": ""
57+
},
58+
{
59+
"description": "X wins crossing from left to right",
60+
"board":
61+
""" . O . .
62+
O X X X
63+
O X O .
64+
X X O X
65+
. O X .""",
66+
"winner": "X"
67+
},
68+
{
69+
"description": "X wins using a convoluted path",
70+
"board":
71+
""" . X X . .
72+
X . X . X
73+
. X . X .
74+
. X X . .
75+
O O O O O""",
76+
"winner": "X"
77+
},
78+
{
79+
"description": "O wins crossing from top to bottom",
80+
"board":
81+
""" . O . .
82+
O X X X
83+
O O O .
84+
X X O X
85+
. O X .""",
86+
"winner": "O"
87+
},
88+
{
89+
"description": "X wins using a spiral path",
90+
"board":
91+
""" O X X X X X X X X
92+
O X O O O O O O O
93+
O X O X X X X X O
94+
O X O X O O O X O
95+
O X O X X X O X O
96+
O X O O O X O X O
97+
O X X X X X O X O
98+
O O O O O O O X O
99+
X X X X X X X X O """,
100+
"winner": "X"
101+
},
102+
]
103+
104+
105+
class ConnectTest(unittest.TestCase):
106+
def test_game(self):
107+
for testcase in testcases:
108+
game = connect.ConnectGame(testcase["board"])
109+
winner = game.get_winner()
110+
expected = testcase["winner"] if testcase["winner"] else "None"
111+
got = winner if winner else "None"
112+
self.assertEqual(winner, testcase["winner"],
113+
"Test failed: %s, expected winner: %s, got: %s"
114+
% (testcase["description"], expected, got))
115+
116+
117+
if __name__ == '__main__':
118+
unittest.main()

exercises/connect/example.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
class ConnectGame:
3+
4+
directions = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, -1), (-1, 1)]
5+
white = "O"
6+
black = "X"
7+
none = ""
8+
9+
def __init__(self, lines):
10+
self.board = self.make_board(lines)
11+
assert len(self.board) > 0
12+
13+
self.width = len(self.board[0])
14+
self.height = len(self.board)
15+
assert self.width > 0 and self.height > 0
16+
17+
for l in self.board:
18+
assert len(l) == self.width
19+
20+
def valid(self, x, y):
21+
return x >= 0 and x < self.width and y >= 0 and y < self.height
22+
23+
def make_board(self, lines):
24+
return ["".join(l.split()) for l in lines.splitlines()]
25+
26+
def player_reach_dest(self, player, x, y):
27+
if player == self.black:
28+
return x == self.width - 1
29+
if player == self.white:
30+
return y == self.height - 1
31+
32+
def walk_board(self, player, x, y, visited=[]):
33+
if (x, y) in visited:
34+
return False
35+
36+
if (not self.valid(x, y)) or self.board[y][x] != player:
37+
return False
38+
39+
if self.player_reach_dest(player, x, y):
40+
return True
41+
42+
for d in self.directions:
43+
if self.walk_board(player, x + d[0], y + d[1], visited + [(x, y)]):
44+
return True
45+
46+
def check_player_is_winner(self, player):
47+
if player == self.black:
48+
for y in range(self.height):
49+
if self.walk_board(player, 0, y):
50+
return True
51+
if player == self.white:
52+
for x in range(self.width):
53+
if self.walk_board(player, x, 0):
54+
return True
55+
56+
def get_winner(self):
57+
if self.check_player_is_winner(self.black):
58+
return self.black
59+
if self.check_player_is_winner(self.white):
60+
return self.white
61+
return self.none

0 commit comments

Comments
 (0)