diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 763de3a9..78b4ce37 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ on: jobs: ci: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout repository diff --git a/config.json b/config.json index 28aa722f..34634f2e 100644 --- a/config.json +++ b/config.json @@ -1282,6 +1282,14 @@ "practices": [], "prerequisites": [], "difficulty": 3 + }, + { + "slug": "bottle-song", + "name": "Bottle Song", + "uuid": "0c786feb-8653-4215-9281-2e1c83afeefe", + "practices": [], + "prerequisites": [], + "difficulty": 3 } ] }, diff --git a/exercises/practice/bottle-song/.docs/instructions.md b/exercises/practice/bottle-song/.docs/instructions.md new file mode 100644 index 00000000..febdfc86 --- /dev/null +++ b/exercises/practice/bottle-song/.docs/instructions.md @@ -0,0 +1,57 @@ +# Instructions + +Recite the lyrics to that popular children's repetitive song: Ten Green Bottles. + +Note that not all verses are identical. + +```text +Ten green bottles hanging on the wall, +Ten green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be nine green bottles hanging on the wall. + +Nine green bottles hanging on the wall, +Nine green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be eight green bottles hanging on the wall. + +Eight green bottles hanging on the wall, +Eight green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be seven green bottles hanging on the wall. + +Seven green bottles hanging on the wall, +Seven green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be six green bottles hanging on the wall. + +Six green bottles hanging on the wall, +Six green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be five green bottles hanging on the wall. + +Five green bottles hanging on the wall, +Five green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be four green bottles hanging on the wall. + +Four green bottles hanging on the wall, +Four green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be three green bottles hanging on the wall. + +Three green bottles hanging on the wall, +Three green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be two green bottles hanging on the wall. + +Two green bottles hanging on the wall, +Two green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be one green bottle hanging on the wall. + +One green bottle hanging on the wall, +One green bottle hanging on the wall, +And if one green bottle should accidentally fall, +There'll be no green bottles hanging on the wall. +``` diff --git a/exercises/practice/bottle-song/.meta/Example.scala b/exercises/practice/bottle-song/.meta/Example.scala new file mode 100644 index 00000000..ba6141a6 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/Example.scala @@ -0,0 +1,17 @@ +object BottleSong: + private val numbers = List("no", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten") + + private def suffix(bottles: Int) = if bottles == 1 then "" else "s" + + private def hanging(bottles: Int) = + s"${numbers(bottles)} green bottle${suffix(bottles)} hanging on the wall" + + private def firstLine(bottles: Int) = hanging(bottles) + ",\n" + + private def lastLine(bottles: Int) = "There'll be " + hanging(bottles).toLowerCase + ".\n" + + private def verse(bottles: Int) = firstLine(bottles).repeat(2) + + "And if one green bottle should accidentally fall,\n" + lastLine(bottles - 1) + + def recite(startBottles: Int, takeDown: Int): String = + startBottles until startBottles - takeDown by -1 map verse mkString "\n" diff --git a/exercises/practice/bottle-song/.meta/config.json b/exercises/practice/bottle-song/.meta/config.json new file mode 100644 index 00000000..9ed4be51 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "rabestro" + ], + "files": { + "solution": [ + "src/main/scala/BottleSong.scala" + ], + "test": [ + "src/test/scala/BottleSongTest.scala" + ], + "example": [ + ".meta/Example.scala" + ] + }, + "blurb": "Produce the lyrics to the popular children's repetitive song: Ten Green Bottles.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Ten_Green_Bottles" +} diff --git a/exercises/practice/bottle-song/.meta/tests.toml b/exercises/practice/bottle-song/.meta/tests.toml new file mode 100644 index 00000000..1f6e40a3 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/tests.toml @@ -0,0 +1,31 @@ +# 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. + +[d4ccf8fc-01dc-48c0-a201-4fbeb30f2d03] +description = "verse -> single verse -> first generic verse" + +[0f0aded3-472a-4c64-b842-18d4f1f5f030] +description = "verse -> single verse -> last generic verse" + +[f61f3c97-131f-459e-b40a-7428f3ed99d9] +description = "verse -> single verse -> verse with 2 bottles" + +[05eadba9-5dbd-401e-a7e8-d17cc9baa8e0] +description = "verse -> single verse -> verse with 1 bottle" + +[a4a28170-83d6-4dc1-bd8b-319b6abb6a80] +description = "lyrics -> multiple verses -> first two verses" + +[3185d438-c5ac-4ce6-bcd3-02c9ff1ed8db] +description = "lyrics -> multiple verses -> last three verses" + +[28c1584a-0e51-4b65-9ae2-fbc0bf4bbb28] +description = "lyrics -> multiple verses -> all verses" diff --git a/exercises/practice/bottle-song/build.sbt b/exercises/practice/bottle-song/build.sbt new file mode 100644 index 00000000..3ac61447 --- /dev/null +++ b/exercises/practice/bottle-song/build.sbt @@ -0,0 +1,3 @@ +scalaVersion := "3.4.2" + +libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % Test \ No newline at end of file diff --git a/exercises/practice/bottle-song/project/build.properties b/exercises/practice/bottle-song/project/build.properties new file mode 100644 index 00000000..ee4c672c --- /dev/null +++ b/exercises/practice/bottle-song/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.1 diff --git a/exercises/practice/bottle-song/src/main/scala/BottleSong.scala b/exercises/practice/bottle-song/src/main/scala/BottleSong.scala new file mode 100644 index 00000000..d4a8a9d0 --- /dev/null +++ b/exercises/practice/bottle-song/src/main/scala/BottleSong.scala @@ -0,0 +1,3 @@ +object BottleSong: + + def recite(startBottles: Int, takeDown: Int): String = ??? diff --git a/exercises/practice/bottle-song/src/test/scala/BottleSongTest.scala b/exercises/practice/bottle-song/src/test/scala/BottleSongTest.scala new file mode 100644 index 00000000..d906ebaf --- /dev/null +++ b/exercises/practice/bottle-song/src/test/scala/BottleSongTest.scala @@ -0,0 +1,134 @@ +import org.scalatest.funsuite.AnyFunSuite +import org.scalatest.matchers.should.Matchers + +class BottleSongTest extends AnyFunSuite with Matchers { + + test("first generic verse") { + BottleSong.recite(10, 1) shouldBe + """Ten green bottles hanging on the wall, + |Ten green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be nine green bottles hanging on the wall. + |""".stripMargin.trim + "\n" + } + + test("last generic verse") { + pending + BottleSong.recite(3, 1) shouldBe + """Three green bottles hanging on the wall, + |Three green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be two green bottles hanging on the wall. + |""".stripMargin.trim + "\n" + } + + test("verse with two bottles") { + pending + BottleSong.recite(2, 1) shouldBe + """Two green bottles hanging on the wall, + |Two green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be one green bottle hanging on the wall. + |""".stripMargin.trim + "\n" + } + + test("verse with one bottle") { + pending + BottleSong.recite(1, 1) shouldBe + """One green bottle hanging on the wall, + |One green bottle hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be no green bottles hanging on the wall. + |""".stripMargin.trim + "\n" + } + + test("first two verses") { + pending + BottleSong.recite(10, 2) shouldBe + """Ten green bottles hanging on the wall, + |Ten green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be nine green bottles hanging on the wall. + | + |Nine green bottles hanging on the wall, + |Nine green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be eight green bottles hanging on the wall. + |""".stripMargin.trim + "\n" + } + + test("last three verses") { + pending + BottleSong.recite(3, 3) shouldBe + """Three green bottles hanging on the wall, + |Three green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be two green bottles hanging on the wall. + | + |Two green bottles hanging on the wall, + |Two green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be one green bottle hanging on the wall. + | + |One green bottle hanging on the wall, + |One green bottle hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be no green bottles hanging on the wall. + |""".stripMargin.trim + "\n" + } + + test("all verses") { + pending + BottleSong.recite(10, 10) shouldBe + """Ten green bottles hanging on the wall, + |Ten green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be nine green bottles hanging on the wall. + | + |Nine green bottles hanging on the wall, + |Nine green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be eight green bottles hanging on the wall. + | + |Eight green bottles hanging on the wall, + |Eight green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be seven green bottles hanging on the wall. + | + |Seven green bottles hanging on the wall, + |Seven green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be six green bottles hanging on the wall. + | + |Six green bottles hanging on the wall, + |Six green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be five green bottles hanging on the wall. + | + |Five green bottles hanging on the wall, + |Five green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be four green bottles hanging on the wall. + | + |Four green bottles hanging on the wall, + |Four green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be three green bottles hanging on the wall. + | + |Three green bottles hanging on the wall, + |Three green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be two green bottles hanging on the wall. + | + |Two green bottles hanging on the wall, + |Two green bottles hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be one green bottle hanging on the wall. + | + |One green bottle hanging on the wall, + |One green bottle hanging on the wall, + |And if one green bottle should accidentally fall, + |There'll be no green bottles hanging on the wall. + |""".stripMargin.trim + "\n" + } +} \ No newline at end of file