4

What's the easiest way in F# (in a functional/recursive style) to, given a number in words, convert it to it's numeric equivalent?

I'm looking at only English for now. E.g:

let parseNumber (s : string) =
    match s with
    | "One" -> 1
    | _ - failwith "Cannot parse"

let result = parseNumber "One Thousand Two Hundred"
// result should be 12000

Is there any way of doing this that doesn't involve a massive look-up table?

Danny Tuppeny
  • 40,147
  • 24
  • 151
  • 275
Tolu
  • 1,081
  • 1
  • 8
  • 23
  • 1
    Oops; my fault on the duplicate close. It was suggested as a dupe, and I read the content but not the language! /cc @DannyTuppeny – Andrew Barber Nov 06 '13 at 15:54
  • Closely related (language-agnostic): [How to read values from numbers written as words?](http://stackoverflow.com/q/70161) – jscs Nov 17 '13 at 04:00

1 Answers1

7

Here's a naive/simple solution, but you'll need to extend it to support all numbers (eg. "Thirty Thousand"):

open System

let parseNumber (s : string) =
    let parts = s.Split ' ' |> Array.rev |> Array.toList
    let rec parseParts (s : string list) =
        match s with
        | [] -> 0
        | "One" :: rest -> 1 + parseParts rest
        | "Two" :: rest -> 2 + parseParts rest
        | "Three" :: rest -> 3 + parseParts rest
        | "Four" :: rest -> 4 + parseParts rest
        | "Five" :: rest -> 5 + parseParts rest
        | "Six" :: rest -> 6 + parseParts rest
        | "Seven" :: rest -> 7 + parseParts rest
        | "Eight" :: rest -> 8 + parseParts rest
        | "Nine" :: rest -> 9 + parseParts rest
        | "Ten" :: rest -> 10 + parseParts rest
        | "Hundred" :: t :: rest -> parseParts [t] * 100 + parseParts rest
        | "Thousand" :: t :: rest -> parseParts [t] * 1000 + parseParts rest
        | _ -> failwith "Ug"
    parseParts parts

parseNumber "One" |> printfn "%i"
parseNumber "Two Hundred" |> printfn "%i"
parseNumber "Three Thousand" |> printfn "%i"
parseNumber "Three Thousand Four" |> printfn "%i"
parseNumber "One Thousand Two Hundred" |> printfn "%i"
Danny Tuppeny
  • 40,147
  • 24
  • 151
  • 275