Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,14 @@
"prerequisites": [],
"difficulty": 8
},
{
"slug": "connect",
"name": "Connect",
"uuid": "8c824d1a-0609-4c72-8a3b-512a8469cc8f",
"practices": [],
"prerequisites": [],
"difficulty": 8
},
{
"slug": "forth",
"name": "Forth",
Expand Down
5 changes: 5 additions & 0 deletions exercises/practice/connect/.busted
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
return {
default = {
ROOT = { '.' }
}
}
27 changes: 27 additions & 0 deletions exercises/practice/connect/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Instructions

Compute the result for a game of Hex / Polygon.

The abstract boardgame known as [Hex][hex] / Polygon / CON-TAC-TIX is quite simple in rules, though complex in practice.
Two players place stones on a parallelogram with hexagonal fields.
The player to connect his/her stones to the opposite side first wins.
The four sides of the parallelogram are divided between the two players (i.e. one player gets assigned a side and the side directly opposite it and the other player gets assigned the two other sides).

Your goal is to build a program that given a simple representation of a board computes the winner (or lack thereof).
Note that all games need not be "fair".
(For example, players may have mismatched piece counts or the game's board might have a different width and height.)

The boards look like this:

```text
. O . X .
. X X O .
O O O X .
. X O X O
X O O O X
```

"Player `O`" plays from top to bottom, "Player `X`" plays from left to right.
In the above example `O` has made a connection from left to right but nobody has won since `O` didn't connect top and bottom.

[hex]: https://en.wikipedia.org/wiki/Hex_%28board_game%29
17 changes: 17 additions & 0 deletions exercises/practice/connect/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"authors": [
"glennj"
],
"files": {
"solution": [
"connect.moon"
],
"test": [
"connect_spec.moon"
],
"example": [
".meta/example.moon"
]
},
"blurb": "Compute the result for a game of Hex / Polygon."
}
38 changes: 38 additions & 0 deletions exercises/practice/connect/.meta/example.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- ---------------------------------------------------
clone = (t) -> [ [c for c in *row] for row in *t]
transpose = (t) ->
[ [t[row][col] for row = 1, #t] for col = 1, #t[1]]

-- ---------------------------------------------------
win = (player, mtx) ->
size = #mtx -- assume square board

-- seed the stack with players on the first row
stack = [{1, i} for i = 1, size when mtx[1][i] == player]
return false if #stack == 0
return true if size == 1

neighbours = (r, c) ->
ns = {}
for {dr, dc} in *{{-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}}
rr, cc = r + dr, c + dc
if rr >= 1 and rr <= size and cc >= 1 and cc <= size
table.insert ns, {rr, cc} if mtx[rr][cc] == player
ns

while #stack > 0
{r, c} = table.remove stack
for {rr, cc} in *neighbours r, c
return true if rr == size -- winner reached the last row
mtx[rr][cc] = '-' -- mark as visited
table.insert stack, {rr, cc}
false

-- ---------------------------------------------------
{
winner: (board) ->
matrix = [ [c for c in row\gmatch '[XO.]'] for row in *board]
return 'O' if win 'O', clone(matrix) -- top to bottom
return 'X' if win 'X', transpose(matrix) -- left to right
return ''
}
13 changes: 13 additions & 0 deletions exercises/practice/connect/.meta/spec_generator.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import string_list from require 'test_helpers'

{
-- one of:
module_name: 'Connect',

generate_test: (case, level) ->
lines = {
"board = #{string_list case.input.board, level}",
"assert.are.equal #{quote case.expected}, Connect.#{case.property} board"
}
table.concat [indent line, level for line in *lines], '\n'
}
46 changes: 46 additions & 0 deletions exercises/practice/connect/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[6eff0df4-3e92-478d-9b54-d3e8b354db56]
description = "an empty board has no winner"

[298b94c0-b46d-45d8-b34b-0fa2ea71f0a4]
description = "X can win on a 1x1 board"

[763bbae0-cb8f-4f28-bc21-5be16a5722dc]
description = "O can win on a 1x1 board"

[819fde60-9ae2-485e-a024-cbb8ea68751b]
description = "only edges does not make a winner"

[2c56a0d5-9528-41e5-b92b-499dfe08506c]
description = "illegal diagonal does not make a winner"

[41cce3ef-43ca-4963-970a-c05d39aa1cc1]
description = "nobody wins crossing adjacent angles"

[cd61c143-92f6-4a8d-84d9-cb2b359e226b]
description = "X wins crossing from left to right"

[495e33ed-30a9-4012-b46e-d7c4d5fe13c3]
description = "X wins with left-hand dead end fork"

[ab167ab0-4a98-4d0f-a1c0-e1cddddc3d58]
description = "X wins with right-hand dead end fork"

[73d1eda6-16ab-4460-9904-b5f5dd401d0b]
description = "O wins crossing from top to bottom"

[c3a2a550-944a-4637-8b3f-1e1bf1340a3d]
description = "X wins using a convoluted path"

[17e76fa8-f731-4db7-92ad-ed2a285d31f3]
description = "X wins using a spiral path"
4 changes: 4 additions & 0 deletions exercises/practice/connect/connect.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
winner: (board) ->
error 'Implement me'
}
111 changes: 111 additions & 0 deletions exercises/practice/connect/connect_spec.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
Connect = require 'connect'

describe 'connect', ->
it 'an empty board has no winner', ->
board = {
'. . . . .',
' . . . . .',
' . . . . .',
' . . . . .',
' . . . . .',
}
assert.are.equal '', Connect.winner board

pending 'X can win on a 1x1 board', ->
board = {'X'}
assert.are.equal 'X', Connect.winner board

pending 'O can win on a 1x1 board', ->
board = {'O'}
assert.are.equal 'O', Connect.winner board

pending 'only edges does not make a winner', ->
board = {
'O O O X',
' X . . X',
' X . . X',
' X O O O',
}
assert.are.equal '', Connect.winner board

pending 'illegal diagonal does not make a winner', ->
board = {
'X O . .',
' O X X X',
' O X O .',
' . O X .',
' X X O O',
}
assert.are.equal '', Connect.winner board

pending 'nobody wins crossing adjacent angles', ->
board = {
'X . . .',
' . X O .',
' O . X O',
' . O . X',
' . . O .',
}
assert.are.equal '', Connect.winner board

pending 'X wins crossing from left to right', ->
board = {
'. O . .',
' O X X X',
' O X O .',
' X X O X',
' . O X .',
}
assert.are.equal 'X', Connect.winner board

pending 'X wins with left-hand dead end fork', ->
board = {
'. . X .',
' X X . .',
' . X X X',
' O O O O',
}
assert.are.equal 'X', Connect.winner board

pending 'X wins with right-hand dead end fork', ->
board = {
'. . X X',
' X X . .',
' . X X .',
' O O O O',
}
assert.are.equal 'X', Connect.winner board

pending 'O wins crossing from top to bottom', ->
board = {
'. O . .',
' O X X X',
' O O O .',
' X X O X',
' . O X .',
}
assert.are.equal 'O', Connect.winner board

pending 'X wins using a convoluted path', ->
board = {
'. X X . .',
' X . X . X',
' . X . X .',
' . X X . .',
' O O O O O',
}
assert.are.equal 'X', Connect.winner board

pending 'X wins using a spiral path', ->
board = {
'O X X X X X X X X',
' O X O O O O O O O',
' O X O X X X X X O',
' O X O X O O O X O',
' O X O X X X O X O',
' O X O O O X O X O',
' O X X X X X O X O',
' O O O O O O O X O',
' X X X X X X X X O',
}
assert.are.equal 'X', Connect.winner board
Loading