diff --git a/config.json b/config.json index cb3de932f..b19696c80 100644 --- a/config.json +++ b/config.json @@ -1580,9 +1580,9 @@ ] }, { - "slug": "minesweeper", - "name": "Minesweeper", - "uuid": "3bf049f8-7283-4370-aa0c-e10e99d9ef80", + "slug": "flower-field", + "name": "Flower Field", + "uuid": "c1900113-f4b2-4a04-a40e-89036e8aba9c", "practices": [], "prerequisites": [], "difficulty": 4, @@ -1594,6 +1594,16 @@ "transforming" ] }, + { + "slug": "minesweeper", + "name": "Minesweeper", + "uuid": "3bf049f8-7283-4370-aa0c-e10e99d9ef80", + "practices": [], + "prerequisites": [], + "difficulty": 4, + "topics": [], + "status": "deprecated" + }, { "slug": "queen-attack", "name": "Queen Attack", diff --git a/exercises/practice/flower-field/.docs/instructions.md b/exercises/practice/flower-field/.docs/instructions.md new file mode 100644 index 000000000..bbdae0c2c --- /dev/null +++ b/exercises/practice/flower-field/.docs/instructions.md @@ -0,0 +1,26 @@ +# Instructions + +Your task is to add flower counts to empty squares in a completed Flower Field garden. +The garden itself is a rectangle board composed of squares that are either empty (`' '`) or a flower (`'*'`). + +For each empty square, count the number of flowers adjacent to it (horizontally, vertically, diagonally). +If the empty square has no adjacent flowers, leave it empty. +Otherwise replace it with the count of adjacent flowers. + +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/flower-field/.docs/introduction.md b/exercises/practice/flower-field/.docs/introduction.md new file mode 100644 index 000000000..af9b61536 --- /dev/null +++ b/exercises/practice/flower-field/.docs/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +[Flower Field][history] is a compassionate reimagining of the popular game Minesweeper. +The object of the game is to find all the flowers in the garden using numeric hints that indicate how many flowers are directly adjacent (horizontally, vertically, diagonally) to a square. +"Flower Field" shipped in regional versions of Microsoft Windows in Italy, Germany, South Korea, Japan and Taiwan. + +[history]: https://web.archive.org/web/20020409051321fw_/http://rcm.usr.dsi.unimi.it/rcmweb/fnm/ diff --git a/exercises/practice/flower-field/.meta/config.json b/exercises/practice/flower-field/.meta/config.json new file mode 100644 index 000000000..5a5283790 --- /dev/null +++ b/exercises/practice/flower-field/.meta/config.json @@ -0,0 +1,32 @@ +{ + "authors": [ + "norbs57" + ], + "contributors": [ + "alebaffa", + "bitfield", + "dvrkps", + "ekingery", + "ferhatelmas", + "hilary", + "kahgoh", + "kytrinyx", + "leenipper", + "petertseng", + "robphoenix", + "sebito91", + "tleen" + ], + "files": { + "solution": [ + "flower_field.go" + ], + "test": [ + "flower_field_test.go" + ], + "example": [ + ".meta/example.go" + ] + }, + "blurb": "Mark all the flowers in a garden." +} diff --git a/exercises/practice/flower-field/.meta/example.go b/exercises/practice/flower-field/.meta/example.go new file mode 100644 index 000000000..18b72c2e1 --- /dev/null +++ b/exercises/practice/flower-field/.meta/example.go @@ -0,0 +1,45 @@ +package flowerfield + +func Annotate(b []string) []string { + result := make([]string, len(b)) + dirX := []int{} + dirY := []int{} + for i := -1; i <= 1; i++ { + for j := -1; j <= 1; j++ { + if i != 0 || j != 0 { + dirX = append(dirX, i) + dirY = append(dirY, j) + } + } + } + inGrid := func(i, j int) bool { + return i >= 0 && j >= 0 && i < len(b) && j < len(b[0]) + } + countForSquare := func(i, j int) int { + result := 0 + for k := range dirX { + i1, j1 := i+dirX[k], j+dirY[k] + if inGrid(i1, j1) && b[i1][j1] == '*' { + result++ + } + } + return result + } + for i, row := range b { + resultRow := make([]rune, len(b[i])) + for j, c := range row { + if row[j] == '*' { + resultRow[j] = c + } else { + count := countForSquare(i, j) + if count == 0 { + resultRow[j] = ' ' + } else { + resultRow[j] = rune('0' + count) + } + } + } + result[i] = string(resultRow) + } + return result +} diff --git a/exercises/practice/flower-field/.meta/tests.toml b/exercises/practice/flower-field/.meta/tests.toml new file mode 100644 index 000000000..c2b24fdaf --- /dev/null +++ b/exercises/practice/flower-field/.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. + +[237ff487-467a-47e1-9b01-8a891844f86c] +description = "no rows" + +[4b4134ec-e20f-439c-a295-664c38950ba1] +description = "no columns" + +[d774d054-bbad-4867-88ae-069cbd1c4f92] +description = "no flowers" + +[225176a0-725e-43cd-aa13-9dced501f16e] +description = "garden full of flowers" + +[3f345495-f1a5-4132-8411-74bd7ca08c49] +description = "flower surrounded by spaces" + +[6cb04070-4199-4ef7-a6fa-92f68c660fca] +description = "space surrounded by flowers" + +[272d2306-9f62-44fe-8ab5-6b0f43a26338] +description = "horizontal line" + +[c6f0a4b2-58d0-4bf6-ad8d-ccf4144f1f8e] +description = "horizontal line, flowers at edges" + +[a54e84b7-3b25-44a8-b8cf-1753c8bb4cf5] +description = "vertical line" + +[b40f42f5-dec5-4abc-b167-3f08195189c1] +description = "vertical line, flowers at edges" + +[58674965-7b42-4818-b930-0215062d543c] +description = "cross" + +[dd9d4ca8-9e68-4f78-a677-a2a70fd7a7b8] +description = "large garden" diff --git a/exercises/practice/flower-field/flower_field.go b/exercises/practice/flower-field/flower_field.go new file mode 100644 index 000000000..ebc5e2c13 --- /dev/null +++ b/exercises/practice/flower-field/flower_field.go @@ -0,0 +1,6 @@ +package flowerfield + +// Annotate returns an annotated board +func Annotate(board []string) []string { + panic("Please implement the Annotate function") +} diff --git a/exercises/practice/flower-field/flower_field_test.go b/exercises/practice/flower-field/flower_field_test.go new file mode 100644 index 000000000..cf41e24fd --- /dev/null +++ b/exercises/practice/flower-field/flower_field_test.go @@ -0,0 +1,205 @@ +package flowerfield + +import ( + "testing" +) + +type flowerfieldTestCase struct { + description string + garden []string + expected []string +} + +var flowerfieldTestCases = []flowerfieldTestCase{ + { + description: "no rows", + garden: []string{}, + expected: []string{}, + }, + { + description: "no columns", + garden: []string{""}, + expected: []string{""}, + }, + { + description: "no flowers", + garden: []string{ + " ", + " ", + " ", + }, + expected: []string{ + " ", + " ", + " ", + }, + }, + { + description: "garden with only flowers", + garden: []string{ + "***", + "***", + "***", + }, + expected: []string{ + "***", + "***", + "***", + }, + }, + { + description: "flower surrounded by spaces", + garden: []string{ + " ", + " * ", + " ", + }, + expected: []string{ + "111", + "1*1", + "111", + }, + }, + { + description: "space surrounded by flowers", + garden: []string{ + "***", + "* *", + "***", + }, + expected: []string{ + "***", + "*8*", + "***", + }, + }, + { + description: "horizontal line", + garden: []string{" * * "}, + expected: []string{"1*2*1"}, + }, + { + description: "horizontal line, flowers at edges", + garden: []string{"* *"}, + expected: []string{"*1 1*"}, + }, + { + description: "vertical line", + garden: []string{ + " ", + "*", + " ", + "*", + " ", + }, + expected: []string{ + "1", + "*", + "2", + "*", + "1", + }, + }, + { + description: "vertical line, flowers at edges", + garden: []string{ + "*", + " ", + " ", + " ", + "*", + }, + expected: []string{ + "*", + "1", + " ", + "1", + "*", + }, + }, + { + description: "cross", + garden: []string{ + " * ", + " * ", + "*****", + " * ", + " * ", + }, + expected: []string{ + " 2*2 ", + "25*52", + "*****", + "25*52", + " 2*2 ", + }, + }, + { + description: "large garden", + garden: []string{ + " * * ", + " * ", + " * ", + " * *", + " * * ", + " ", + }, + expected: []string{ + "1*22*1", + "12*322", + " 123*2", + "112*4*", + "1*22*2", + "111111", + }, + }, +} + +func slicesEqual(a, b []string) bool { + if len(a) != len(b) { + return false + } + if len(a) == 0 { + return true + } + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + return true +} + +func TestAnnotate(t *testing.T) { + for _, tc := range flowerfieldTestCases { + t.Run(tc.description, func(t *testing.T) { + got := Annotate(tc.garden) + want := tc.expected + if !slicesEqual(want, got) { + t.Fatalf("expected: %v, got: %v", want, got) + } + }) + } +} + +var benchmarkResult []string + +func BenchmarkAnnotate(b *testing.B) { + if testing.Short() { + b.Skip("skipping benchmark in short mode.") + } + var result []string + board := []string{ + "1*22*1", + "12*322", + " 123*2", + "112*4*", + "1*22*2", + "111111", + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + result = Annotate(board) + } + benchmarkResult = result +} diff --git a/exercises/practice/flower-field/go.mod b/exercises/practice/flower-field/go.mod new file mode 100644 index 000000000..784c66dde --- /dev/null +++ b/exercises/practice/flower-field/go.mod @@ -0,0 +1,3 @@ +module flowerfield + +go 1.18