diff --git a/config.json b/config.json index e9de12a..4787028 100644 --- a/config.json +++ b/config.json @@ -408,6 +408,14 @@ "prerequisites": [], "difficulty": 4 }, + { + "slug": "bottle-song", + "name": "Bottle Song", + "uuid": "13485ed2-274b-4bfb-9b50-fb9586f1da89", + "practices": [], + "prerequisites": [], + "difficulty": 4 + }, { "slug": "atbash-cipher", "name": "Atbash Cipher", diff --git a/exercises/practice/bottle-song/.docs/instructions.md b/exercises/practice/bottle-song/.docs/instructions.md new file mode 100644 index 0000000..febdfc8 --- /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/config.json b/exercises/practice/bottle-song/.meta/config.json new file mode 100644 index 0000000..aeac7d6 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "bottle-song.wren" + ], + "test": [ + "bottle-song.spec.wren" + ], + "example": [ + ".meta/proof.ci.wren" + ] + }, + "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/proof.ci.wren b/exercises/practice/bottle-song/.meta/proof.ci.wren new file mode 100644 index 0000000..48119b9 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/proof.ci.wren @@ -0,0 +1,46 @@ +class BottleSong { + static toTitleCase(description) { + var first = String.fromCodePoint(description.codePoints[0] - 32) + var rest = description[1..-1] + return first + rest + } + + static describe(numBottles) { + var names = [ + "no", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "ten" + ] + var suffix = "s" + if (numBottles == 1) { + suffix = "" + } + return "%(names[numBottles]) green bottle%(suffix)" + } + + static recite(startBottles, takeDown) { + var result = [] + var currentBottles = startBottles + for (i in 0...takeDown) { + var description = toTitleCase(describe(currentBottles)) + result.add("%(description) hanging on the wall,") + result.add("%(description) hanging on the wall,") + result.add("And if one green bottle should accidentally fall,") + currentBottles = currentBottles - 1 + description = describe(currentBottles) + result.add("There'll be %(description) hanging on the wall.") + if (i + 1 < takeDown) { + result.add("") + } + } + return result + } +} diff --git a/exercises/practice/bottle-song/.meta/tests.toml b/exercises/practice/bottle-song/.meta/tests.toml new file mode 100644 index 0000000..1f6e40a --- /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/LICENSE b/exercises/practice/bottle-song/LICENSE new file mode 100644 index 0000000..ef5d211 --- /dev/null +++ b/exercises/practice/bottle-song/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Exercism + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/exercises/practice/bottle-song/bottle-song.spec.wren b/exercises/practice/bottle-song/bottle-song.spec.wren new file mode 100644 index 0000000..5aa067b --- /dev/null +++ b/exercises/practice/bottle-song/bottle-song.spec.wren @@ -0,0 +1,134 @@ +import "./bottle-song" for BottleSong +import "wren-testie/testie" for Testie, Expect + +Testie.test("BottleSong.recite()") { |do, skip| + do.test("verse -> single verse -> first generic verse") { + var expected = [ + "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.", + ] + Expect.value(BottleSong.recite(10, 1)).toEqual(expected) + } + + skip.test("verse -> single verse -> last generic verse") { + var expected = [ + "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.", + ] + Expect.value(BottleSong.recite(3, 1)).toEqual(expected) + } + + skip.test("verse -> single verse -> verse with 2 bottles") { + var expected = [ + "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.", + ] + Expect.value(BottleSong.recite(2, 1)).toEqual(expected) + } + + skip.test("verse -> single verse -> verse with 1 bottle") { + var expected = [ + "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.", + ] + Expect.value(BottleSong.recite(1, 1)).toEqual(expected) + } + + skip.test("lyrics -> multiple verses -> first two verses") { + var expected = [ + "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.", + ] + Expect.value(BottleSong.recite(10, 2)).toEqual(expected) + } + + skip.test("lyrics -> multiple verses -> last three verses") { + var expected = [ + "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.", + ] + Expect.value(BottleSong.recite(3, 3)).toEqual(expected) + } + + skip.test("lyrics -> multiple verses -> all verses") { + var expected = [ + "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.", + ] + Expect.value(BottleSong.recite(10, 10)).toEqual(expected) + } +} diff --git a/exercises/practice/bottle-song/bottle-song.wren b/exercises/practice/bottle-song/bottle-song.wren new file mode 100644 index 0000000..7c0446b --- /dev/null +++ b/exercises/practice/bottle-song/bottle-song.wren @@ -0,0 +1,5 @@ +class BottleSong { + static recite(startBottles, takeDown) { + Fiber.abort("Remove this statement and implement this function") + } +} diff --git a/exercises/practice/bottle-song/package.wren b/exercises/practice/bottle-song/package.wren new file mode 100644 index 0000000..ca9287c --- /dev/null +++ b/exercises/practice/bottle-song/package.wren @@ -0,0 +1,14 @@ +import "wren-package" for WrenPackage, Dependency +import "os" for Process + +class Package is WrenPackage { + construct new() {} + name { "exercism/bottle-song" } + dependencies { + return [ + Dependency.new("wren-testie", "0.3.0", "https://github.com/joshgoebel/wren-testie.git") + ] + } +} + +Package.new().default()