Repository: exercism/clojure
Pull request #203 (2017-12-20 23:41:31)

say: add to track
Add `say` exercise to clojure track


Patch:
diff --git a/config.json b/config.json
index 13eb5b1..929a6f7 100644
--- a/config.json
+++ b/config.json
@@ -57,6 +57,14 @@
       "unlocked_by": null,
       "uuid": "04ac2bd0-504c-4faa-912e-d2111b46123c"
     },
+    {
+      "core": false,
+      "difficulty": 1,
+      "slug": "say",
+      "topics": null,
+      "unlocked_by": null,
+      "uuid": "31aa2618-b971-44ff-9799-761fdec53b87"
+    },
     {
       "core": false,
       "difficulty": 1,
diff --git a/exercises/say/README.md b/exercises/say/README.md
new file mode 100644
index 0000000..e97b51c
--- /dev/null
+++ b/exercises/say/README.md
@@ -0,0 +1,70 @@
+# Say
+
+Given a number from 0 to 999,999,999,999, spell out that number in English.
+
+## Step 1
+
+Handle the basic case of 0 through 99.
+
+If the input to the program is `22`, then the output should be
+`'twenty-two'`.
+
+Your program should complain loudly if given a number outside the
+blessed range.
+
+Some good test cases for this program are:
+
+- 0
+- 14
+- 50
+- 98
+- -1
+- 100
+
+### Extension
+
+If you're on a Mac, shell out to Mac OS X's `say` program to talk out
+loud.
+
+## Step 2
+
+Implement breaking a number up into chunks of thousands.
+
+So `1234567890` should yield a list like 1, 234, 567, and 890, while the
+far simpler `1000` should yield just 1 and 0.
+
+The program must also report any values that are out of range.
+
+## Step 3
+
+Now handle inserting the appropriate scale word between those chunks.
+
+So `1234567890` should yield `'1 billion 234 million 567 thousand 890'`
+
+The program must also report any values that are out of range.  It's
+fine to stop at "trillion".
+
+## Step 4
+
+Put it all together to get nothing but plain English.
+
+`12345` should give `twelve thousand three hundred forty-five`.
+
+The program must also report any values that are out of range.
+
+### Extensions
+
+Use _and_ (correctly) when spelling out the number in English:
+
+- 14 becomes "fourteen".
+- 100 becomes "one hundred".
+- 120 becomes "one hundred and twenty".
+- 1002 becomes "one thousand and two".
+- 1323 becomes "one thousand three hundred and twenty-three".
+
+## Source
+
+This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
+
+## Submitting Incomplete Solutions
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/exercises/say/project.clj b/exercises/say/project.clj
new file mode 100644
index 0000000..217b060
--- /dev/null
+++ b/exercises/say/project.clj
@@ -0,0 +1,4 @@
+(defproject say "0.1.0-SNAPSHOT"
+  :description "say exercise."
+  :url "https://github.com/exercism/clojure/tree/master/exercises/say"
+  :dependencies [[org.clojure/clojure "1.8.0"]])
diff --git a/exercises/say/src/example.clj b/exercises/say/src/example.clj
new file mode 100644
index 0000000..81ffc4a
--- /dev/null
+++ b/exercises/say/src/example.clj
@@ -0,0 +1,9 @@
+(ns say
+    (:require [clojure.pprint :as pp]
+              [clojure.string :as s]))
+
+(defn number [input]
+  (if
+    (or (< input 0) (> input 999999999999))
+    (throw (IllegalArgumentException. "Out of range"))
+    (s/replace (pp/cl-format nil "~R" input) #"," "")))
diff --git a/exercises/say/src/say.clj b/exercises/say/src/say.clj
new file mode 100644
index 0000000..342a621
--- /dev/null
+++ b/exercises/say/src/say.clj
@@ -0,0 +1,5 @@
+(ns say)
+
+(defn number [] ;; <- arglist goes here
+  ;; your code goes here
+)


Test patch:
diff --git a/exercises/say/test/say_test.clj b/exercises/say/test/say_test.clj
new file mode 100644
index 0000000..1ccb57e
--- /dev/null
+++ b/exercises/say/test/say_test.clj
@@ -0,0 +1,48 @@
+(ns say-test
+  (:require [clojure.test :refer [deftest is]]
+            say))
+
+(deftest zero-test
+  (is (= "zero" (say/number 0))))
+
+(deftest one-test
+  (is (= "one" (say/number 1))))
+
+(deftest fourteen-test
+  (is (= "fourteen" (say/number 14))))
+
+(deftest twenty-test
+  (is (= "twenty" (say/number 20))))
+
+(deftest twenty-two-test
+  (is (= "twenty-two" (say/number 22))))
+
+(deftest one-hundred-test
+  (is (= "one hundred" (say/number 100))))
+
+(deftest one-hundred-twenty-three-test
+  (is (= "one hundred twenty-three" (say/number 123))))
+
+(deftest one-thousand-test
+  (is (= "one thousand" (say/number 1000))))
+
+(deftest one-thousand-two-hundred-thirty-four-test
+  (is (= "one thousand two hundred thirty-four" (say/number 1234))))
+
+(deftest one-million-test
+  (is (= "one million" (say/number 1000000))))
+
+(deftest one-million-two-thousand-three-hundred-forty-five-test
+  (is (= "one million two thousand three hundred forty-five" (say/number 1002345))))
+
+(deftest one-billion-test
+  (is (= "one billion" (say/number 1000000000))))
+
+(deftest a-big-number-test
+  (is (= "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three" (say/number 987654321123))))
+
+(deftest below-zero-is-out-of-range-test
+  (is (thrown? IllegalArgumentException (say/number -1))))
+
+(deftest numbers-above-999999999999-out-of-range-test
+  (is (thrown? IllegalArgumentException (say/number 1000000000000))))