diff --git a/config.json b/config.json index 5cf4ab0c..986a91b2 100644 --- a/config.json +++ b/config.json @@ -1192,6 +1192,14 @@ "optional_values" ] }, + { + "slug": "flower-field", + "name": "Flower Field", + "uuid": "33043a5a-4360-43c6-a5bd-0e9c3f4b9069", + "practices": [], + "prerequisites": [], + "difficulty": 7 + }, { "slug": "minesweeper", "name": "Minesweeper", @@ -1199,6 +1207,7 @@ "practices": [], "prerequisites": [], "difficulty": 7, + "status": "deprecated", "topics": [ "lists", "parsing", diff --git a/exercises/practice/flower-field/.docs/instructions.md b/exercises/practice/flower-field/.docs/instructions.md new file mode 100644 index 00000000..bbdae0c2 --- /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 00000000..af9b6153 --- /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/Example.scala b/exercises/practice/flower-field/.meta/Example.scala new file mode 100644 index 00000000..2a3a63e2 --- /dev/null +++ b/exercises/practice/flower-field/.meta/Example.scala @@ -0,0 +1,32 @@ +class Board(rows: List[String]) { + lazy val annotate: List[String] = + (for (y <- 0 until numRows) yield annotateRow(y)).toList + + private lazy val numRows = rows.length + private lazy val numCols = if (rows.isEmpty) 0 else rows.head.length + private lazy val boardVector = rows.toVector.map(_.toVector) + + private def annotateRow(y: Int) = + (for (x <- 0 until numCols) yield annotateSquare(x, y)).mkString + + private def annotateSquare(x: Int, y: Int) = + if (hasFlower(x, y)) flowerChar + else neighborsWithFlowers(x, y) match { + case 0 => ' ' + case n => (n + '0').toChar + } + + private def neighborsWithFlowers(x: Int, y: Int) = (for ( + yNeighbor <- Math.max(0, y - 1) to Math.min(numRows - 1, y + 1); + xNeighbor <- Math.max(0, x - 1) to Math.min(numCols - 1, x + 1) + if (yNeighbor != y || xNeighbor != x) && hasFlower(xNeighbor, yNeighbor) + ) yield ()).length + + private def hasFlower(x: Int, y: Int) = isFlowerChar(boardVector(y)(x)) + private def isFlowerChar(c: Char) = c == flowerChar + private val flowerChar = '*' +} + +object FlowerField { + def annotate(board: List[String]): List[String] = new Board(board).annotate +} diff --git a/exercises/practice/flower-field/.meta/config.json b/exercises/practice/flower-field/.meta/config.json new file mode 100644 index 00000000..d6f599fb --- /dev/null +++ b/exercises/practice/flower-field/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "ricemery" + ], + "contributors": [ + "ErikSchierboom", + "keiravillekode", + "ppartarr", + "rajeshpg" + ], + "files": { + "solution": [ + "src/main/scala/FlowerField.scala" + ], + "test": [ + "src/test/scala/FlowerFieldTest.scala" + ], + "example": [ + ".meta/Example.scala" + ] + }, + "blurb": "Mark all the flowers in a garden." +} diff --git a/exercises/practice/flower-field/.meta/tests.toml b/exercises/practice/flower-field/.meta/tests.toml new file mode 100644 index 00000000..c2b24fda --- /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/build.sbt b/exercises/practice/flower-field/build.sbt new file mode 100644 index 00000000..803f8dc0 --- /dev/null +++ b/exercises/practice/flower-field/build.sbt @@ -0,0 +1,3 @@ +scalaVersion := "3.4.2" + +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test diff --git a/exercises/practice/flower-field/project/build.properties b/exercises/practice/flower-field/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/flower-field/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/flower-field/src/main/scala/FlowerField.scala b/exercises/practice/flower-field/src/main/scala/FlowerField.scala new file mode 100644 index 00000000..f2e4b66d --- /dev/null +++ b/exercises/practice/flower-field/src/main/scala/FlowerField.scala @@ -0,0 +1,3 @@ +object FlowerField { + def annotate(board: List[String]): List[String] = ??? +} diff --git a/exercises/practice/flower-field/src/test/scala/FlowerFieldTest.scala b/exercises/practice/flower-field/src/test/scala/FlowerFieldTest.scala new file mode 100644 index 00000000..eda3e0a9 --- /dev/null +++ b/exercises/practice/flower-field/src/test/scala/FlowerFieldTest.scala @@ -0,0 +1,124 @@ +import org.scalatest.funsuite.AnyFunSuite +import org.scalatest.matchers.should.Matchers + + +/** @version 1.1.0 */ +class FlowerFieldTest extends AnyFunSuite with Matchers { + + test("no rows") { + FlowerField.annotate(List()) should be(List()) + } + + test("no columns") { + pending + FlowerField.annotate(List("")) should be(List("")) + } + + test("no flowers") { + pending + FlowerField.annotate(List(" ", + " ", + " ")) should be( + List(" ", + " ", + " ")) + } + + test("garden with only flowers") { + pending + FlowerField.annotate(List("***", + "***", + "***")) should be( + List("***", + "***", + "***")) + } + + test("flower surrounded by spaces") { + pending + FlowerField.annotate(List(" ", + " * ", + " ")) should be( + List("111", + "1*1", + "111")) + } + + test("space surrounded by flowers") { + pending + FlowerField.annotate(List("***", + "* *", + "***")) should be( + List("***", + "*8*", + "***")) + } + + test("horizontal line") { + pending + FlowerField.annotate(List(" * * ")) should be(List("1*2*1")) + } + + test("horizontal line, flowers at edges") { + pending + FlowerField.annotate(List("* *")) should be(List("*1 1*")) + } + + test("vertical line") { + pending + FlowerField.annotate(List(" ", + "*", + " ", + "*", + " ")) should be( + List("1", + "*", + "2", + "*", + "1")) + } + + test("vertical line, flowers at edges") { + pending + FlowerField.annotate(List("*", + " ", + " ", + " ", + "*")) should be( + List("*", + "1", + " ", + "1", + "*")) + } + + test("cross") { + pending + FlowerField.annotate(List(" * ", + " * ", + "*****", + " * ", + " * ")) should be( + List(" 2*2 ", + "25*52", + "*****", + "25*52", + " 2*2 ")) + } + + test("large garden") { + pending + FlowerField.annotate(List(" * * ", + " * ", + " * ", + " * *", + " * * ", + " ")) should be( + List("1*22*1", + "12*322", + " 123*2", + "112*4*", + "1*22*2", + "111111")) + } +}