# MaximeLM's solution

## to Say in the Swift Track

Published at Jul 13 2018 · 0 comments
Instructions
Test suite
Solution

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".

## Setup

Go through the project setup instructions for Xcode using Swift:

http://exercism.io/languages/swift

## Source

A variation on JavaRanch CattleDrive, exercise 4a http://www.javaranch.com/say.jsp

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### LinuxMain.swift

``````import XCTest
@testable import SayTests

XCTMain([
testCase(SayTests.allTests),
])``````

### SayTests.swift

``````import XCTest
@testable import Say

class SayTests: XCTestCase {

func testZero() {
XCTAssertEqual("zero", Say.say(0))
}

func testOne() {
XCTAssertEqual("one", Say.say(1))
}

func testFourteen() {
XCTAssertEqual("fourteen", Say.say(14))
}

func testTwenty() {
XCTAssertEqual("twenty", Say.say(20))
}

func testTwentyTwo() {
XCTAssertEqual("twenty-two", Say.say(22))
}

func testOneHundred() {
XCTAssertEqual("one hundred", Say.say(100))
}

func testOneHundredTwentyThree() {
XCTAssertEqual("one hundred twenty-three", Say.say(123))
}

func testOneThousand() {
XCTAssertEqual("one thousand", Say.say(1_000))
}

func testOneThousandTwoHundredThirtyFour() {
XCTAssertEqual("one thousand two hundred thirty-four", Say.say(1_234))
}

func testOneMillion() {
XCTAssertEqual("one million", Say.say(1_000_000))
}

func testOneMillionTwoThousandThreeHundredFortyFive() {
XCTAssertEqual("one million two thousand three hundred forty-five", Say.say(1_002_345))
}

func testOneBillion() {
XCTAssertEqual("one billion", Say.say(1_000_000_000))
}

func testABigNumber() {
XCTAssertEqual("nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three", Say.say(987_654_321_123))
}

func testNumbersBelowZeroAreOutOfRange() {
XCTAssertNil(Say.say(-1))
}

func testNumbersAbove999999999999AreOutOfRange() {
XCTAssertNil(Say.say(1_000_000_000_000))
}

static var allTests: [(String, (SayTests) -> () throws -> Void)] {
return [
("testZero", testZero),
("testOne", testOne),
("testFourteen", testFourteen),
("testTwenty", testTwenty),
("testTwentyTwo", testTwentyTwo),
("testOneHundred", testOneHundred),
("testOneHundredTwentyThree", testOneHundredTwentyThree),
("testOneThousand", testOneThousand),
("testOneThousandTwoHundredThirtyFour", testOneThousandTwoHundredThirtyFour),
("testOneMillion", testOneMillion),
("testOneMillionTwoThousandThreeHundredFortyFive", testOneMillionTwoThousandThreeHundredFortyFive),
("testOneBillion", testOneBillion),
("testABigNumber", testABigNumber),
("testNumbersBelowZeroAreOutOfRange", testNumbersBelowZeroAreOutOfRange),
("testNumbersAbove999999999999AreOutOfRange", testNumbersAbove999999999999AreOutOfRange),
]
}
}``````
``````func say(_ n: Int) -> String? {
guard n < 1_000_000_000_000 else {
return nil
}
guard n < 1_000_000_000 else {
let part1 = "\(say(n / 1_000_000_000) ?? "") billion"
if n % 1_000_000_000 == 0 {
return part1
} else {
return "\(part1) \(say(n % 1_000_000_000) ?? "")"
}
}
guard n < 1_000_000 else {
let part1 = "\(say(n / 1_000_000) ?? "") million"
if n % 1_000_000 == 0 {
return part1
} else {
return "\(part1) \(say(n % 1_000_000) ?? "")"
}
}
guard n < 1_000 else {
let part1 = "\(say(n / 1_000) ?? "") thousand"
if n % 1_000 == 0 {
return part1
} else {
return "\(part1) \(say(n % 1_000) ?? "")"
}
}
guard n < 100 else {
let part1 = "\(say(n / 100) ?? "") hundred"
if n % 100 == 0 {
return part1
} else {
return "\(part1) \(say(n % 100) ?? "")"
}
}
switch n {
case 0: return "zero"
case 1: return "one"
case 2: return "two"
case 3: return "three"
case 4: return "four"
case 5: return "five"
case 6: return "six"
case 7: return "seven"
case 8: return "eight"
case 9: return "nine"
case 10: return "ten"
case 11: return "eleven"
case 12: return "twelve"
case 13: return "thirteen"
case 14: return "fourteen"
case 15: return "fifteen"
case 16: return "sixteen"
case 17: return "seventeen"
case 18: return "eighteen"
case 19: return "nineteen"
case 20: return "twenty"
case 30: return "thirty"
case 40: return "forty"
case 50: return "fifty"
case 60: return "sixty"
case 70: return "seventy"
case 80: return "eighty"
case 90: return "ninety"
case 21...99: return "\(say(n - n % 10) ?? "")-\(say(n % 10) ?? "")"
default: return nil
}
}``````