Skip to content

Commit 503768e

Browse files
Implementing "say" exercise for R track (#394)
* Adding say exercise to R track * put example and stub in the right places * Update example.R changed `small.n` to `small_n` and added spaces aound `=` to fix linter warnings. * Update test_say.R Added `# nolint` to a long line --------- Co-authored-by: Colin Leach <[email protected]>
1 parent 9dacc68 commit 503768e

File tree

7 files changed

+326
-1
lines changed

7 files changed

+326
-1
lines changed

config.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@
554554
"prerequisites": [],
555555
"difficulty": 5,
556556
"topics": [
557-
"math"
557+
"math"
558558
]
559559
},
560560
{
@@ -931,6 +931,14 @@
931931
"practices": [],
932932
"prerequisites": [],
933933
"difficulty": 4
934+
},
935+
{
936+
"slug": "say",
937+
"name": "Say",
938+
"uuid": "c87b10f2-0920-4fdc-9143-a879708b24f2",
939+
"practices": [],
940+
"prerequisites": [],
941+
"difficulty": 5
934942
}
935943
]
936944
},
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Instructions
2+
3+
Given a number from 0 to 999,999,999,999, spell out that number in English.
4+
5+
## Step 1
6+
7+
Handle the basic case of 0 through 99.
8+
9+
If the input to the program is `22`, then the output should be `'twenty-two'`.
10+
11+
Your program should complain loudly if given a number outside the blessed range.
12+
13+
Some good test cases for this program are:
14+
15+
- 0
16+
- 14
17+
- 50
18+
- 98
19+
- -1
20+
- 100
21+
22+
### Extension
23+
24+
If you're on a Mac, shell out to Mac OS X's `say` program to talk out loud.
25+
If you're on Linux or Windows, eSpeakNG may be available with the command `espeak`.
26+
27+
## Step 2
28+
29+
Implement breaking a number up into chunks of thousands.
30+
31+
So `1234567890` should yield a list like 1, 234, 567, and 890, while the far simpler `1000` should yield just 1 and 0.
32+
33+
## Step 3
34+
35+
Now handle inserting the appropriate scale word between those chunks.
36+
37+
So `1234567890` should yield `'1 billion 234 million 567 thousand 890'`
38+
39+
The program must also report any values that are out of range.
40+
It's fine to stop at "trillion".
41+
42+
## Step 4
43+
44+
Put it all together to get nothing but plain English.
45+
46+
`12345` should give `twelve thousand three hundred forty-five`.
47+
48+
The program must also report any values that are out of range.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"frequenter-at-exercism"
4+
],
5+
"files": {
6+
"solution": [
7+
"say.R"
8+
],
9+
"test": [
10+
"test_say.R"
11+
],
12+
"example": [
13+
".meta/example.R"
14+
]
15+
},
16+
"blurb": "Given a number from 0 to 999,999,999,999, spell out that number in English.",
17+
"source": "A variation on the JavaRanch CattleDrive, Assignment 4",
18+
"source_url": "https://web.archive.org/web/20240907035912/https://coderanch.com/wiki/718804"
19+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
small_n <- c(
2+
'one',
3+
'two',
4+
'three',
5+
'four',
6+
'five',
7+
'six',
8+
'seven',
9+
'eight',
10+
'nine',
11+
'ten',
12+
'eleven',
13+
'twelve',
14+
'thirteen',
15+
'fourteen',
16+
'fifteen',
17+
'sixteen',
18+
'seventeen',
19+
'eighteen',
20+
'nineteen')
21+
22+
tens <- c(
23+
'ten',
24+
'twenty',
25+
'thirty',
26+
'forty',
27+
'fifty',
28+
'sixty',
29+
'seventy',
30+
'eighty',
31+
'ninety')
32+
33+
oom <- c('billion', 'million', 'thousand', '')
34+
35+
say_group <- \(n) {
36+
h <- n %/% 100
37+
if (h == 0) sh <- c()
38+
else sh <- c(small_n[h], 'hundred')
39+
r <- n %% 100
40+
if (r < 20) sh <- c(sh, small_n[r])
41+
else sh <- c(sh, tens[r %/% 10])
42+
last <- r %% 10
43+
if (last > 0 && r >= 20) sh <- c(sh, '-', small_n[last])
44+
sh
45+
}
46+
47+
group <- \(number) {
48+
groups <- rep(0, 4)
49+
for (i in 4:1) {
50+
groups[i] <- number %% 1000
51+
number <- number %/% 1000
52+
}
53+
groups
54+
}
55+
56+
say <- \(number) {
57+
if (number < 0 || number >= 1e12) stop('input out of range')
58+
if (number == 0) return('zero')
59+
groups <- group(number)
60+
sh <- c()
61+
for (i in 1:3) {
62+
if (groups[i] > 0) {
63+
sh <- c(sh, say_group(groups[i]), oom[i])
64+
}
65+
}
66+
sh <- c(sh, say_group(groups[4]))
67+
gsub(' - ', '-', paste(sh, collapse = ' '))
68+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[5d22a120-ba0c-428c-bd25-8682235d83e8]
13+
description = "zero"
14+
15+
[9b5eed77-dbf6-439d-b920-3f7eb58928f6]
16+
description = "one"
17+
18+
[7c499be1-612e-4096-a5e1-43b2f719406d]
19+
description = "fourteen"
20+
21+
[f541dd8e-f070-4329-92b4-b7ce2fcf06b4]
22+
description = "twenty"
23+
24+
[d78601eb-4a84-4bfa-bf0e-665aeb8abe94]
25+
description = "twenty-two"
26+
27+
[f010d4ca-12c9-44e9-803a-27789841adb1]
28+
description = "thirty"
29+
30+
[738ce12d-ee5c-4dfb-ad26-534753a98327]
31+
description = "ninety-nine"
32+
33+
[e417d452-129e-4056-bd5b-6eb1df334dce]
34+
description = "one hundred"
35+
36+
[d6924f30-80ba-4597-acf6-ea3f16269da8]
37+
description = "one hundred twenty-three"
38+
39+
[2f061132-54bc-4fd4-b5df-0a3b778959b9]
40+
description = "two hundred"
41+
42+
[feed6627-5387-4d38-9692-87c0dbc55c33]
43+
description = "nine hundred ninety-nine"
44+
45+
[3d83da89-a372-46d3-b10d-de0c792432b3]
46+
description = "one thousand"
47+
48+
[865af898-1d5b-495f-8ff0-2f06d3c73709]
49+
description = "one thousand two hundred thirty-four"
50+
51+
[b6a3f442-266e-47a3-835d-7f8a35f6cf7f]
52+
description = "one million"
53+
54+
[2cea9303-e77e-4212-b8ff-c39f1978fc70]
55+
description = "one million two thousand three hundred forty-five"
56+
57+
[3e240eeb-f564-4b80-9421-db123f66a38f]
58+
description = "one billion"
59+
60+
[9a43fed1-c875-4710-8286-5065d73b8a9e]
61+
description = "a big number"
62+
63+
[49a6a17b-084e-423e-994d-a87c0ecc05ef]
64+
description = "numbers below zero are out of range"
65+
66+
[4d6492eb-5853-4d16-9d34-b0f61b261fd9]
67+
description = "numbers above 999,999,999,999 are out of range"

exercises/practice/say/say.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
say <- function(number) {
2+
}

exercises/practice/say/test_say.R

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
source("./say.R")
2+
library(testthat)
3+
4+
test_that("zero", {
5+
expect_equal(
6+
say(0),
7+
"zero")
8+
})
9+
10+
test_that("one", {
11+
expect_equal(
12+
say(1),
13+
"one")
14+
})
15+
16+
test_that("fourteen", {
17+
expect_equal(
18+
say(14),
19+
"fourteen")
20+
})
21+
22+
test_that("twenty", {
23+
expect_equal(
24+
say(20),
25+
"twenty")
26+
})
27+
28+
test_that("twenty-two", {
29+
expect_equal(
30+
say(22),
31+
"twenty-two")
32+
})
33+
34+
test_that("thirty", {
35+
expect_equal(
36+
say(30),
37+
"thirty")
38+
})
39+
40+
test_that("ninety-nine", {
41+
expect_equal(
42+
say(99),
43+
"ninety-nine")
44+
})
45+
46+
test_that("one hundred", {
47+
expect_equal(
48+
say(100),
49+
"one hundred")
50+
})
51+
52+
test_that("one hundred twenty-three", {
53+
expect_equal(
54+
say(123),
55+
"one hundred twenty-three")
56+
})
57+
58+
test_that("two hundred", {
59+
expect_equal(
60+
say(200),
61+
"two hundred")
62+
})
63+
64+
test_that("nine hundred ninety-nine", {
65+
expect_equal(
66+
say(999),
67+
"nine hundred ninety-nine")
68+
})
69+
70+
test_that("one thousand", {
71+
expect_equal(
72+
say(1000),
73+
"one thousand")
74+
})
75+
76+
test_that("one thousand two hundred thirty-four", {
77+
expect_equal(
78+
say(1234),
79+
"one thousand two hundred thirty-four")
80+
})
81+
82+
test_that("one million", {
83+
expect_equal(
84+
say(1000000),
85+
"one million")
86+
})
87+
88+
test_that("one million two thousand three hundred forty-five", {
89+
expect_equal(
90+
say(1002345),
91+
"one million two thousand three hundred forty-five")
92+
})
93+
94+
test_that("one billion", {
95+
expect_equal(
96+
say(1000000000),
97+
"one billion")
98+
})
99+
100+
test_that("a big number", {
101+
expect_equal(
102+
say(987654321123),
103+
"nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three") # nolint
104+
})
105+
106+
test_that("numbers below zero are out of range", {
107+
expect_error(say(-1), "input out of range")
108+
})
109+
110+
test_that("numbers above 999,999,999,999 are out of range", {
111+
expect_error(say(1000000000000),
112+
"input out of range")
113+
})

0 commit comments

Comments
 (0)