Say a Number

Saksham

With the Corona-Lockdown in place “literally”, it was time to squeeze out some me-time to continue the quest for GO-Proficiency.

Sometimes you re-do optimization in your head so many times that it takes a whole day to see through the mistake you are making.

Trying to solve problem – Say.

input: 123,

expected: “one hundred twenty-three”,

For every such input number you need to translate and provide the English output.

The max limit goes till out a 100 billion.

I started it with a standard map definition which has few constants already in place.

var myMap = map[int]string{
    0:          "zero", // 0 - Starts with zero.
    1:          "one",
    2:          "two",
    3:          "three",
    4:          "four",
    5:          "five",
    6:          "six",
    7:          "seven",
    8:          "eight",
    9:          "nine",
    10:         "ten",
    11:         "eleven",
    12:         "twelve",
    13:         "thirteen",
    20:         "twenty",
    30:         "thirty",
    40:         "fourty",
    50:         "fifty",
    60:         "sixty",
    70:         "seventy",
    80:         "eighty",
    90:         "ninety",
    100:        "hundred",
    1000:       "thousand",
    1000000:    "million",
    1000000000: "billion",
}

Step – 1

Addressing all numbers less than 100.

//tens It is a function that will convert < 100
func tens(i int) (string, bool) {

    // Valid for numbers less than hundred only.
    switch {
    case i > 13 && i < 20:
        return fmt.Sprintf("%s%s", myMap[i-10], "teen"), true
    case i > 20 && i < 29:
        return fmt.Sprintf("%s%s", "twenty-", myMap[i-20]), true
    case i > 30 && i < 40:
        return fmt.Sprintf("%s%s", "thirty-", myMap[i-30]), true
    case i > 40 && i < 50:
        return fmt.Sprintf("%s%s", "forty-", myMap[i-40]), true
    case i > 50 && i < 60:
        return fmt.Sprintf("%s%s", "fifty-", myMap[i-50]), true
    case i > 60 && i < 70:
        return fmt.Sprintf("%s%s", "sixty-", myMap[i-60]), true
    case i > 70 && i < 80:
        return fmt.Sprintf("%s%s", "seventy-", myMap[i-70]), true
    case i > 80 && i < 90:
        return fmt.Sprintf("%s%s", "eighty-", myMap[i-80]), true
    case i > 90 && i < 100:
        return fmt.Sprintf("%s%s", "ninety-", myMap[i-90]), true
    default:
        // If there is a numeric equivalent available in map.
        if val, ok := myMap[int(i)]; ok {
            return val, true
        }
    }

    //No match found in map or can be calculated
    return "", false
}

Now time to build the logic upwards

//NumberConversion Converts the number
func NumberConversion(i int64) (string, bool) {
    var s strings.Builder

    for i >= 0 {
        switch {
        case i == 0:
            if len(s.String()) == 0 {
                if val, ok := tens(int(i)); ok {
                    fmt.Fprintf(&s, " %s", val)
                }
            }
            return strings.TrimSpace(s.String()), true
        case i < 100:
            if val, ok := tens(int(i)); ok {
                fmt.Fprintf(&s, " %s", val)
            }
            return strings.TrimSpace(s.String()), true
         }
    }
    return "", false
}

This function allows all number conversion for elements less than 100 by calling the NumberConversion function.

Step – 2 Number > 100 < 1000

Added a hundreds function

// hundreds Allows to compute the numeric equivalent of the 100-999
func hundreds(r int) (string, bool) {
    switch {
    case r == 0:
        return fmt.Sprintf("one %s", myMap[100]), true
    default:
        return fmt.Sprintf("%s %s", myMap[r], myMap[100]), true
    }
}

and adding a new case to the function NumberConversion

     case i >= 100 && i < 1000:
            r := int(i / 100)
            if val, ok := hundreds(r); ok {
                fmt.Fprintf(&s, " %s", val)
            }
            i %= 100

Similarly for elements greater than 1000

     case i >= 1000 && i < 1000000:
            r := i / 1000
            if val, ok := NumberConversion(r); ok {
                fmt.Fprintf(&s, " %s %s", val, myMap[1000])
            }
            i %= 1000

For elements greater than million

      case i >= 1000000 && i < 1000000000:
            r := i / 1000000
            if val, ok := NumberConversion(r); ok {
                fmt.Fprintf(&s, " %s %s", val, myMap[1000000])
            }
            i %= 1000000

And the last billion and less than 100 billion.

      case i >= 1000000000 && i < 1000000000000:
            r := i / 1000000000
            if val, ok := NumberConversion(r); ok {
                fmt.Fprintf(&s, "%s %s", val, myMap[1000000000])
            }
            i %= 1000000000

Finally the function looks like below

//NumberConversion Converts the number
func NumberConversion(i int64) (string, bool) {
    var s strings.Builder

    for i >= 0 {
        switch {
        case i == 0:
            if len(s.String()) == 0 {
                if val, ok := tens(int(i)); ok {
                    fmt.Fprintf(&s, " %s", val)
                }
            }
            return strings.TrimSpace(s.String()), true
        case i < 100:
            if val, ok := tens(int(i)); ok {
                fmt.Fprintf(&s, " %s", val)
            }
            return strings.TrimSpace(s.String()), true
        case i >= 100 && i < 1000:
            r := int(i / 100)
            if val, ok := hundreds(r); ok {
                fmt.Fprintf(&s, " %s", val)
            }
            i %= 100
        case i >= 1000 && i < 1000000:
            r := i / 1000
            if val, ok := NumberConversion(r); ok {
                fmt.Fprintf(&s, " %s %s", val, myMap[1000])
            }
            i %= 1000
        case i >= 1000000 && i < 1000000000:
            r := i / 1000000
            if val, ok := NumberConversion(r); ok {
                fmt.Fprintf(&s, " %s %s", val, myMap[1000000])
            }
            i %= 1000000
        case i >= 1000000000 && i < 1000000000000:
            r := i / 1000000000
            if val, ok := NumberConversion(r); ok {
                fmt.Fprintf(&s, "%s %s", val, myMap[1000000000])
            }
            i %= 1000000000
        }
    }
    return "", false
}
  • All code available here

— THE – END —