diff --git a/config.json b/config.json index 26cb0a6..e8d01d9 100644 --- a/config.json +++ b/config.json @@ -803,6 +803,14 @@ "difficulty": 6, "status": "deprecated" }, + { + "slug": "say", + "name": "Say", + "uuid": "20d8ebd6-682c-4cde-8783-4c2ff508642a", + "practices": [], + "prerequisites": [], + "difficulty": 6 + }, { "slug": "book-store", "name": "Book Store", diff --git a/exercises/practice/say/.docs/instructions.md b/exercises/practice/say/.docs/instructions.md new file mode 100644 index 0000000..3251c51 --- /dev/null +++ b/exercises/practice/say/.docs/instructions.md @@ -0,0 +1,12 @@ +# Instructions + +Given a number, your task is to express it in English words exactly as your friend should say it out loud. +Yaʻqūb expects to use numbers from 0 up to 999,999,999,999. + +Examples: + +- 0 → zero +- 1 → one +- 12 → twelve +- 123 → one hundred twenty-three +- 1,234 → one thousand two hundred thirty-four diff --git a/exercises/practice/say/.docs/introduction.md b/exercises/practice/say/.docs/introduction.md new file mode 100644 index 0000000..abd2285 --- /dev/null +++ b/exercises/practice/say/.docs/introduction.md @@ -0,0 +1,6 @@ +# Introduction + +Your friend Yaʻqūb works the counter at the busiest deli in town, slicing, weighing, and wrapping orders for a never-ending line of hungry customers. +To keep things moving, each customer takes a numbered ticket when they arrive. + +When it’s time to call the next person, Yaʻqūb reads their number out loud, always in full English words to make sure everyone hears it clearly. diff --git a/exercises/practice/say/.meta/config.json b/exercises/practice/say/.meta/config.json new file mode 100644 index 0000000..0f5a3fa --- /dev/null +++ b/exercises/practice/say/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "source/say.d" + ], + "test": [ + "source/say.d" + ], + "example": [ + "example/say.d" + ] + }, + "blurb": "Given a number from 0 to 999,999,999,999, spell out that number in English.", + "source": "A variation on the JavaRanch CattleDrive, Assignment 4", + "source_url": "https://web.archive.org/web/20240907035912/https://coderanch.com/wiki/718804" +} diff --git a/exercises/practice/say/.meta/tests.toml b/exercises/practice/say/.meta/tests.toml new file mode 100644 index 0000000..a5532e9 --- /dev/null +++ b/exercises/practice/say/.meta/tests.toml @@ -0,0 +1,67 @@ +# 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. + +[5d22a120-ba0c-428c-bd25-8682235d83e8] +description = "zero" + +[9b5eed77-dbf6-439d-b920-3f7eb58928f6] +description = "one" + +[7c499be1-612e-4096-a5e1-43b2f719406d] +description = "fourteen" + +[f541dd8e-f070-4329-92b4-b7ce2fcf06b4] +description = "twenty" + +[d78601eb-4a84-4bfa-bf0e-665aeb8abe94] +description = "twenty-two" + +[f010d4ca-12c9-44e9-803a-27789841adb1] +description = "thirty" + +[738ce12d-ee5c-4dfb-ad26-534753a98327] +description = "ninety-nine" + +[e417d452-129e-4056-bd5b-6eb1df334dce] +description = "one hundred" + +[d6924f30-80ba-4597-acf6-ea3f16269da8] +description = "one hundred twenty-three" + +[2f061132-54bc-4fd4-b5df-0a3b778959b9] +description = "two hundred" + +[feed6627-5387-4d38-9692-87c0dbc55c33] +description = "nine hundred ninety-nine" + +[3d83da89-a372-46d3-b10d-de0c792432b3] +description = "one thousand" + +[865af898-1d5b-495f-8ff0-2f06d3c73709] +description = "one thousand two hundred thirty-four" + +[b6a3f442-266e-47a3-835d-7f8a35f6cf7f] +description = "one million" + +[2cea9303-e77e-4212-b8ff-c39f1978fc70] +description = "one million two thousand three hundred forty-five" + +[3e240eeb-f564-4b80-9421-db123f66a38f] +description = "one billion" + +[9a43fed1-c875-4710-8286-5065d73b8a9e] +description = "a big number" + +[49a6a17b-084e-423e-994d-a87c0ecc05ef] +description = "numbers below zero are out of range" + +[4d6492eb-5853-4d16-9d34-b0f61b261fd9] +description = "numbers above 999,999,999,999 are out of range" diff --git a/exercises/practice/say/dub.sdl b/exercises/practice/say/dub.sdl new file mode 100644 index 0000000..fe08082 --- /dev/null +++ b/exercises/practice/say/dub.sdl @@ -0,0 +1,2 @@ +name "say" +buildRequirements "disallowDeprecations" diff --git a/exercises/practice/say/example/say.d b/exercises/practice/say/example/say.d new file mode 100644 index 0000000..67ae19f --- /dev/null +++ b/exercises/practice/say/example/say.d @@ -0,0 +1,107 @@ +module say; + +import std.array : appender; + +immutable string[] names = [ + "zero ", + "one ", + "two ", + "three ", + "four ", + "five ", + "six ", + "seven ", + "eight ", + "nine ", + "ten ", + "eleven ", + "twelve ", + "thirteen ", + "fourteen ", + "fifteen ", + "sixteen ", + "seventeen ", + "eighteen ", + "nineteen ", +]; + +immutable string[] decadeNames = [ + "zero", + "ten", + "twenty", + "thirty", + "forty", + "fifty", + "sixty", + "seventy", + "eighty", + "ninety", +]; + +pure string pronounce(long number) +{ + auto builder = appender!string(); + int hundreds = cast(int)(number) / 100; + int units = cast(int)(number) % 100; + if (hundreds != 0) + { + builder.put(names[hundreds]); + builder.put("hundred "); + } + if (units >= 20) + { + builder.put(decadeNames[units / 10]); + if (units % 10 != 0) + { + builder.put("-"); + builder.put(names[units % 10]); + } + else + { + builder.put(" "); + } + } + else if (units != 0) + { + builder.put(names[units]); + } + return builder.data; +} + +pure string say(long number) +{ + if (number < 0 || number > 999999999999) + { + throw new Exception("input out of range"); + } + if (number == 0) + { + return "zero"; + } + auto builder = appender!string(); + long billions = number / 1000000000; + long millions = number / 1000000 % 1000; + long thousands = number / 1000 % 1000; + long units = number % 1000; + if (billions != 0) + { + builder.put(pronounce(billions)); + builder.put("billion "); + } + if (millions != 0) + { + builder.put(pronounce(millions)); + builder.put("million "); + } + if (thousands != 0) + { + builder.put(pronounce(thousands)); + builder.put("thousand "); + } + if (units != 0) + { + builder.put(pronounce(units)); + } + string result = builder.data; + return result[0 .. $ - 1]; +} diff --git a/exercises/practice/say/source/say.d b/exercises/practice/say/source/say.d new file mode 100644 index 0000000..f5b5104 --- /dev/null +++ b/exercises/practice/say/source/say.d @@ -0,0 +1,91 @@ +module say; + +pure string say(long number) +{ + // implement this function +} + +unittest +{ + import std.algorithm.comparison : equal; + import std.exception : assertThrown; + + immutable int allTestsEnabled = 0; + + // Zero + assert(equal("zero", + say(0L))); + + static if (allTestsEnabled) + { + // One + assert(equal("one", + say(1L))); + + // Fourteen + assert(equal("fourteen", + say(14L))); + + // Twenty + assert(equal("twenty", + say(20L))); + + // Twenty-two + assert(equal("twenty-two", + say(22L))); + + // Thirty + assert(equal("thirty", + say(30L))); + + // Ninety-nine + assert(equal("ninety-nine", + say(99L))); + + // One hundred + assert(equal("one hundred", + say(100L))); + + // One hundred twenty-three + assert(equal("one hundred twenty-three", + say(123L))); + + // Two hundred + assert(equal("two hundred", + say(200L))); + + // Nine hundred ninety-nine + assert(equal("nine hundred ninety-nine", + say(999L))); + + // One thousand + assert(equal("one thousand", + say(1000L))); + + // One thousand two hundred thirty-four + assert(equal("one thousand two hundred thirty-four", + say(1234L))); + + // One million + assert(equal("one million", + say(1000000L))); + + // One million two thousand three hundred forty-five + assert(equal("one million two thousand three hundred forty-five", + say(1002345L))); + + // One billion + assert(equal("one billion", + say(1000000000L))); + + // A big number + assert(equal("nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three", + say(987654321123L))); + + // Numbers below zero are out of range + assertThrown(say(-1L)); + + // Numbers above 999,999,999,999 are out of range + assertThrown(say(1000000000000L)); + } +}