From e9fcb7682261fc9cc62e601404f2f6aef94b1962 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 28 Aug 2016 13:04:34 +0200 Subject: Solve say --- go/say/README.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ go/say/say.go | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ go/say/say_test.go | 47 +++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 go/say/README.md create mode 100644 go/say/say.go create mode 100644 go/say/say_test.go diff --git a/go/say/README.md b/go/say/README.md new file mode 100644 index 0000000..426af71 --- /dev/null +++ b/go/say/README.md @@ -0,0 +1,81 @@ +# Say + +Write a program that will take a number from 0 to 999,999,999,999 and 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". + +To run the tests simply run the command `go test` in the exercise directory. + +If the test suite contains benchmarks, you can run these with the `-bench` +flag: + + go test -bench . + +For more detailed info about the Go track see the [help +page](http://exercism.io/languages/go). + +## Source + +A variation on JavaRanch CattleDrive, exercise 4a [http://www.javaranch.com/say.jsp](http://www.javaranch.com/say.jsp) + +## Submitting Incomplete Problems +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + diff --git a/go/say/say.go b/go/say/say.go new file mode 100644 index 0000000..4fdc5b4 --- /dev/null +++ b/go/say/say.go @@ -0,0 +1,74 @@ +package say + +import "strings" + +var small = []string{ + "", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", + "eleven", "twelve", "thirteen", "fourteen", "fifteen", + "sixteen", "seventeen", "eighteen", "nineteen", +} + +var tens = []string{ + "", "", "twenty", "thirty", "forty", "fifty", + "sixty", "seventy", "eighty", "ninety", +} + +var scale = []string{ + "", "thousand", "million", "billion", "trillion", + "quadrillion", "quintillion", +} + +type Group struct { + Value uint64 + Power int +} + +func (g Group) String() string { + var s []string + if h := g.Value / 100; h > 0 { + s = append(s, small[h]+" hundred") + } + if t := g.Value % 100; t > 0 { + if tns := t / 10; tns >= 2 { + if sml := t % 10; sml > 0 { + s = append(s, tens[tns]+"-"+small[sml]) + } else { + s = append(s, tens[tns]) + } + } else if t > 0 { + s = append(s, small[t]) + } + } + if p := scale[g.Power]; p != "" && len(s) > 0 { + s = append(s, p) + } + return strings.Join(s, " ") +} + +func split(n uint64) []Group { + var g []Group + for i := 0; n > 0; i++ { + r := n % 1e3 + n /= 1e3 + g = append(g, Group{ + Value: r, + Power: i, + }) + } + return g +} + +func Say(n uint64) string { + if n <= 0 { + return "zero" + } + g := split(n) + var s []string + for i := len(g) - 1; i >= 0; i-- { + if str := g[i].String(); str != "" { + s = append(s, str) + } + } + return strings.Join(s, " ") +} diff --git a/go/say/say_test.go b/go/say/say_test.go new file mode 100644 index 0000000..e4144a5 --- /dev/null +++ b/go/say/say_test.go @@ -0,0 +1,47 @@ +package say + +// The steps are interesting, but all that matters is the final exam. + +import ( + "math" + "testing" +) + +var tests = []struct { + uint64 + string +}{ + {1, "one"}, + {14, "fourteen"}, + {20, "twenty"}, + {22, "twenty-two"}, + {100, "one hundred"}, + {120, "one hundred twenty"}, + {123, "one hundred twenty-three"}, + {1000, "one thousand"}, + {1234, "one thousand two hundred thirty-four"}, + {1000000, "one million"}, + {1000002, "one million two"}, + {1002345, "one million two thousand three hundred forty-five"}, + {1e9, "one billion"}, + {987654321123, "nine hundred eighty-seven billion " + + "six hundred fifty-four million " + + "three hundred twenty-one thousand " + + "one hundred twenty-three"}, + {0, "zero"}, + {math.MaxUint64, "eighteen quintillion " + + "four hundred forty-six quadrillion " + + "seven hundred forty-four trillion " + + "seventy-three billion " + + "seven hundred nine million " + + "five hundred fifty-one thousand " + + "six hundred fifteen"}, +} + +func TestSay(t *testing.T) { + for _, test := range tests { + if s := Say(test.uint64); s != test.string { + t.Errorf("Say(%d) = %q. Want %q.", test.uint64, s, test.string) + } + } +} -- cgit v1.2.3