diff --git a/config.json b/config.json index ff94d80..e372a18 100644 --- a/config.json +++ b/config.json @@ -672,6 +672,14 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "minesweeper", + "name": "Minesweeper", + "uuid": "ece26c46-07dc-49ae-bac2-10353fb340b5", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "nucleotide-count", "name": "Nucleotide Count", diff --git a/exercises/practice/minesweeper/.docs/instructions.md b/exercises/practice/minesweeper/.docs/instructions.md new file mode 100644 index 0000000..7c1df2e --- /dev/null +++ b/exercises/practice/minesweeper/.docs/instructions.md @@ -0,0 +1,26 @@ +# Instructions + +Your task is to add the mine counts to empty squares in a completed Minesweeper board. +The board itself is a rectangle composed of squares that are either empty (`' '`) or a mine (`'*'`). + +For each empty square, count the number of mines adjacent to it (horizontally, vertically, diagonally). +If the empty square has no adjacent mines, leave it empty. +Otherwise replace it with the adjacent mines count. + +For example, you may receive a 5 x 4 board like this (empty spaces are represented here with the '·' character for display on screen): + +```text +·*·*· +··*·· +··*·· +····· +``` + +Which your code should transform into this: + +```text +1*3*1 +13*31 +·2*2· +·111· +``` diff --git a/exercises/practice/minesweeper/.docs/introduction.md b/exercises/practice/minesweeper/.docs/introduction.md new file mode 100644 index 0000000..5f74a74 --- /dev/null +++ b/exercises/practice/minesweeper/.docs/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +[Minesweeper][wikipedia] is a popular game where the user has to find the mines using numeric hints that indicate how many mines are directly adjacent (horizontally, vertically, diagonally) to a square. + +[wikipedia]: https://en.wikipedia.org/wiki/Minesweeper_(video_game) diff --git a/exercises/practice/minesweeper/.meta/config.json b/exercises/practice/minesweeper/.meta/config.json new file mode 100644 index 0000000..6d7d0d6 --- /dev/null +++ b/exercises/practice/minesweeper/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "minesweeper.vim" + ], + "test": [ + "minesweeper.vader" + ], + "example": [ + ".meta/example.vim" + ] + }, + "blurb": "Add the numbers to a minesweeper board." +} diff --git a/exercises/practice/minesweeper/.meta/example.vim b/exercises/practice/minesweeper/.meta/example.vim new file mode 100644 index 0000000..f506639 --- /dev/null +++ b/exercises/practice/minesweeper/.meta/example.vim @@ -0,0 +1,41 @@ +function! Annotate(minefield) abort + if empty(a:minefield) + return [] + endif + + let l:rows = len(a:minefield) + let l:cols = len(a:minefield[0]) + + let l:result = [] + for l:row in range(l:rows) + let l:marked = [] + for l:col in range(l:cols) + if a:minefield[l:row][l:col] ==# '*' + call add(l:marked, '*') + else + let l:count = 0 + let l:minRow = max([0, l:row - 1]) + let l:maxRow = min([l:rows - 1, l:row + 1]) + let l:minCol = max([0, l:col - 1]) + let l:maxCol = min([l:cols - 1, l:col + 1]) + for l:newRow in range(l:minRow, l:maxRow) + for l:newCol in range(l:minCol, l:maxCol) + if l:newRow == l:row && l:newCol == l:col + continue + endif + if a:minefield[l:newRow][l:newCol] ==# '*' + let l:count += 1 + endif + endfor + endfor + if l:count == 0 + call add(l:marked, ' ') + else + call add(l:marked, l:count) + endif + endif + endfor + call add(result, join(l:marked, '')) + endfor + return result +endfunction diff --git a/exercises/practice/minesweeper/.meta/tests.toml b/exercises/practice/minesweeper/.meta/tests.toml new file mode 100644 index 0000000..2a14222 --- /dev/null +++ b/exercises/practice/minesweeper/.meta/tests.toml @@ -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. + +[0c5ec4bd-dea7-4138-8651-1203e1cb9f44] +description = "no rows" + +[650ac4c0-ad6b-4b41-acde-e4ea5852c3b8] +description = "no columns" + +[6fbf8f6d-a03b-42c9-9a58-b489e9235478] +description = "no mines" + +[61aff1c4-fb31-4078-acad-cd5f1e635655] +description = "minefield with only mines" + +[84167147-c504-4896-85d7-246b01dea7c5] +description = "mine surrounded by spaces" + +[cb878f35-43e3-4c9d-93d9-139012cccc4a] +description = "space surrounded by mines" + +[7037f483-ddb4-4b35-b005-0d0f4ef4606f] +description = "horizontal line" + +[e359820f-bb8b-4eda-8762-47b64dba30a6] +description = "horizontal line, mines at edges" + +[c5198b50-804f-47e9-ae02-c3b42f7ce3ab] +description = "vertical line" + +[0c79a64d-703d-4660-9e90-5adfa5408939] +description = "vertical line, mines at edges" + +[4b098563-b7f3-401c-97c6-79dd1b708f34] +description = "cross" + +[04a260f1-b40a-4e89-839e-8dd8525abe0e] +description = "large minefield" diff --git a/exercises/practice/minesweeper/minesweeper.vader b/exercises/practice/minesweeper/minesweeper.vader new file mode 100644 index 0000000..05c66c2 --- /dev/null +++ b/exercises/practice/minesweeper/minesweeper.vader @@ -0,0 +1,125 @@ +Execute (no rows): + let g:minefield = [] + let g:expected = [] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (no columns): + let g:minefield = [''] + let g:expected = [''] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (no mines): + let g:minefield = [ + \ ' ', + \ ' ', + \ ' '] + let g:expected = [ + \ ' ', + \ ' ', + \ ' '] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (minefield with only mines): + let g:minefield = [ + \ '***', + \ '***', + \ '***'] + let g:expected = [ + \ '***', + \ '***', + \ '***'] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (mine surrounded by spaces): + let g:minefield = [ + \ ' ', + \ ' * ', + \ ' '] + let g:expected = [ + \ '111', + \ '1*1', + \ '111'] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (space surrounded by mines): + let g:minefield = [ + \ '***', + \ '* *', + \ '***'] + let g:expected = [ + \ '***', + \ '*8*', + \ '***'] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (horizontal line): + let g:minefield = [' * * '] + let g:expected = ['1*2*1'] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (horizontal line, mines at edges): + let g:minefield = ['* *'] + let g:expected = ['*1 1*'] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (vertical line): + let g:minefield = [ + \ ' ', + \ '*', + \ ' ', + \ '*', + \ ' '] + let g:expected = [ + \ '1', + \ '*', + \ '2', + \ '*', + \ '1'] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (vertical line, mines at edges): + let g:minefield = [ + \ '*', + \ ' ', + \ ' ', + \ ' ', + \ '*'] + let g:expected = [ + \ '*', + \ '1', + \ ' ', + \ '1', + \ '*'] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (cross): + let g:minefield = [ + \ ' * ', + \ ' * ', + \ '*****', + \ ' * ', + \ ' * '] + let g:expected = [ + \ ' 2*2 ', + \ '25*52', + \ '*****', + \ '25*52', + \ ' 2*2 '] + AssertEqual g:expected, Annotate(g:minefield) + +Execute (large minefield): + let g:minefield = [ + \ ' * * ', + \ ' * ', + \ ' * ', + \ ' * *', + \ ' * * ', + \ ' '] + let g:expected = [ + \ '1*22*1', + \ '12*322', + \ ' 123*2', + \ '112*4*', + \ '1*22*2', + \ '111111'] + AssertEqual g:expected, Annotate(g:minefield) diff --git a/exercises/practice/minesweeper/minesweeper.vim b/exercises/practice/minesweeper/minesweeper.vim new file mode 100644 index 0000000..a59614a --- /dev/null +++ b/exercises/practice/minesweeper/minesweeper.vim @@ -0,0 +1,7 @@ +" +" Given a a list of strings representing a minefield, +" mark each cell with the number of mines in the adjacent cells. +" +function Annotate(minefield) abort + " your code goes here +endfunction