Skip to content

Add say #383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,14 @@
"prerequisites": [],
"difficulty": 5
},
{
"slug": "say",
"name": "Say",
"uuid": "0f01ba32-e46b-47ac-93c7-e0c3739424ae",
"practices": [],
"prerequisites": [],
"difficulty": 5
},
{
"slug": "spiral-matrix",
"name": "Spiral Matrix",
Expand Down
12 changes: 12 additions & 0 deletions exercises/practice/say/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions exercises/practice/say/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -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.
19 changes: 19 additions & 0 deletions exercises/practice/say/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"BNAndras"
],
"files": {
"solution": [
"say.coffee"
],
"test": [
"say.spec.coffee"
],
"example": [
".meta/example.coffee"
]
},
"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"
}
68 changes: 68 additions & 0 deletions exercises/practice/say/.meta/example.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
class Say
@say: (number) ->
throw new Error 'input out of range' if number < 0 or number > 999999999999

if number is 0
return 'zero'

chunks = @chunksFromRight number.toString()
words = (chunks.map Number).map @toWords.bind @
words = words.map @applyScale.bind @
words = words.filter (word) -> word isnt ''
words.reverse().join(' ')

@chunksFromRight: (str) ->
chunks = []
working = str

while working.length > 0
chunks.push working.slice -3
working = working.slice 0, -3

chunks

@toWords: (chunk) ->
words = []
if chunk < 20
words.push @firstTwentyNumbers[chunk]
else if chunk < 100
tens = @wordsForTens[Math.floor(chunk / 10)]
ones = @firstTwentyNumbers[chunk % 10]
if ones
words.push "#{tens}-#{ones}"
else
words.push tens
else
hundreds = @firstTwentyNumbers[Math.floor(chunk / 100)]
rest = @toWords(chunk % 100)
if rest
words.push "#{hundreds} hundred #{rest}"
else
words.push "#{hundreds} hundred"

words.join ' '

@applyScale: (word, index) ->
if word is ''
return ''
if index == 0
return word
if index == 1
return "#{word} thousand"
if index == 2
return "#{word} million"
if index == 3
return "#{word} billion"
else
return word

@firstTwentyNumbers: [
'', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten',
'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
]

@wordsForTens: [
'', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'
]

module.exports = Say
67 changes: 67 additions & 0 deletions exercises/practice/say/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 4 additions & 0 deletions exercises/practice/say/say.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Say
@say: (number) ->

module.exports = Say
66 changes: 66 additions & 0 deletions exercises/practice/say/say.spec.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
Say = require './say'

describe 'Say', ->
it 'zero', ->
expect(Say.say 0).toEqual 'zero'

xit 'one', ->
expect(Say.say 1).toEqual 'one'

xit 'fourteen', ->
expect(Say.say 14).toEqual 'fourteen'

xit 'twenty', ->
expect(Say.say 20).toEqual 'twenty'

xit 'twenty-two', ->
expect(Say.say 22).toEqual 'twenty-two'

xit 'thirty', ->
expect(Say.say 30).toEqual 'thirty'

xit 'ninety-nine', ->
expect(Say.say 99).toEqual 'ninety-nine'

xit 'one hundred', ->
expect(Say.say 100).toEqual 'one hundred'

xit 'one hundred twenty-three', ->
expect(Say.say 123).toEqual 'one hundred twenty-three'

xit 'two hundred', ->
expect(Say.say 200).toEqual 'two hundred'

xit 'nine hundred ninety-nine', ->
expect(Say.say 999).toEqual 'nine hundred ninety-nine'

xit 'one thousand', ->
expect(Say.say 1000).toEqual 'one thousand'

xit 'one thousand two hundred thirty-four', ->
expect(Say.say 1234).toEqual 'one thousand two hundred thirty-four'

xit 'one million', ->
expect(Say.say 1000000).toEqual 'one million'

xit 'one million two thousand three hundred forty-five', ->
expect(Say.say 1002345).toEqual 'one million two thousand three hundred forty-five'

xit 'one billion', ->
expect(Say.say 1000000000).toEqual 'one billion'

xit 'a big number', ->
expect(Say.say 987654321123).toEqual 'nine hundred eighty-seven billion ' +
'six hundred fifty-four million ' +
'three hundred twenty-one thousand ' +
'one hundred twenty-three'

xit 'numbers below zero are out of range', ->
expect ->
Say.say -1
.toThrow new Error 'input out of range'

xit 'numbers above 999,999,999,999 are out of range', ->
expect ->
Say.say 1000000000000
.toThrow new Error 'input out of range'