Хаскелл
Як і в інших рекурсивних рішеннях, я думаю, але я зайняв час, щоб зробити це чистим.
Ось повне джерело з усіма поясненнями: http://ideone.com/fc8zcB
-- Define a type for a parser from a list of tokens to the value they represent.
type NParse = [Token] -> Int
-- Map of literal tokens (0-9, 11-19 and tens) to their names.
literals = [
("zero", 0), ("one", 1), ("two", 2), ("three", 3), ("four", 4), ("five", 5), ("six", 6), ("seven", 7), ("eight", 8), ("nine", 9),
("eleven", 11), ("twelve", 12), ("thirteen", 13), ("fourteen", 14), ("fifteen", 15), ("sixteen", 16), ("seventeen", 17), ("eighteen", 18), ("nineteen", 19),
("ten", 10), ("twenty", 20), ("thirty", 30), ("fourty", 40), ("fifty", 50), ("sixty", 60), ("seventy", 70), ("eighty", 80), ("ninety", 90)
]
-- Splits the input string into tokens.
-- We do one special transformation: replace dshes by a new token. Such that "fifty-three" becomes "fifty tens three".
prepare :: String -> [Token]
-- Let's do the easy stuff and just parse literals first. We just have to look them up in the literals map.
-- This is our base parser.
parseL :: NParse
parseL [tok] = case lookup tok literals of
Just x -> x
-- We're going to exploit the fact that the input strings have a tree-like structure like so
-- thousand
-- hundred hundred
-- ten ten ten ten
-- lit lit lit lit lit lit lit lit
-- And recursively parse that tree until we only have literal values.
--
-- When parsing the tree
-- thousand
-- h1 h2
-- The resulting value is 1000 * h1 + h2.
-- And this works similarly for all levels of the tree.
-- So instead of writing specific parsers for all levels, let's just write a generic one :
{- genParse ::
NParse : the sub parser
-> Int : the left part multiplier
-> Token : the boundary token
-> NParse : returns a new parser -}
genParse :: NParse -> Int -> Token -> NParse
genParse delegate mul tok = newParser where
newParser [] = 0
newParser str = case splitAround str tok of
-- Split around the boundary token, sub-parse the left and right parts, and combine them
(l,r) -> (delegate l) * mul + (delegate r)
-- And so here's the result:
parseNumber :: String -> Int
parseNumber = parseM . prepare
where -- Here are all intermediary parsers for each level
parseT = genParse parseL 1 "tens" -- multiplier is irregular, because the fifty in fifty-three is already multiplied by 10
parseH = genParse parseT 100 "hundred"
parseK = genParse parseH 1000 "thousand"
parseM = genParse parseK 1000000 "million" -- For fun :D
test = (parseNumber "five hundred twenty-three thousand six hundred twelve million two thousand one") == 523612002001