<?php
function words_to_number($data) {
// Replace all number words with an equivalent numeric value
$data,
'zero' => '0',
'a' => '1',
'one' => '1',
'two' => '2',
'three' => '3',
'four' => '4',
'five' => '5',
'six' => '6',
'seven' => '7',
'eight' => '8',
'nine' => '9',
'ten' => '10',
'eleven' => '11',
'twelve' => '12',
'thirteen' => '13',
'fourteen' => '14',
'fifteen' => '15',
'sixteen' => '16',
'seventeen' => '17',
'eighteen' => '18',
'nineteen' => '19',
'twenty' => '20',
'thirty' => '30',
'forty' => '40',
'fourty' => '40', // common misspelling
'fifty' => '50',
'sixty' => '60',
'seventy' => '70',
'eighty' => '80',
'ninety' => '90',
'hundred' => '100',
'thousand' => '1000',
'million' => '1000000',
'billion' => '1000000000',
'and' => '',
)
);
// Coerce all tokens to numbers
function ($val) {
},
);
$stack = new SplStack; // Current work stack
$sum = 0; // Running total
$last = null;
foreach ($parts as $part) {
if (!$stack->isEmpty()) {
// We're part way through a phrase
if ($stack->top() > $part) {
// Decreasing step, e.g. from hundreds to ones
if ($last >= 1000) {
// If we drop from more than 1000 then we've finished the phrase
$sum += $stack->pop();
// This is the first element of a new phrase
$stack->push($part);
} else {
// Drop down from less than 1000, just addition
// e.g. "seventy one" -> "70 1" -> "70 + 1"
$stack->push($stack->pop() + $part);
}
} else {
// Increasing step, e.g ones to hundreds
$stack->push($stack->pop() * $part);
}
} else {
// This is the first element of a new phrase
$stack->push($part);
}
// Store the last processed part
$last = $part;
}
return $sum + $stack->pop();
}
// test
$words = 'five';
echo words_to_number($words);
PD9waHAKCmZ1bmN0aW9uIHdvcmRzX3RvX251bWJlcigkZGF0YSkgewogICAgLy8gUmVwbGFjZSBhbGwgbnVtYmVyIHdvcmRzIHdpdGggYW4gZXF1aXZhbGVudCBudW1lcmljIHZhbHVlCiAgICAkZGF0YSA9IHN0cnRyKAogICAgICAgICRkYXRhLAogICAgICAgIGFycmF5KAogICAgICAgICAgICAnemVybycgICAgICA9PiAnMCcsCiAgICAgICAgICAgICdhJyAgICAgICAgID0+ICcxJywKICAgICAgICAgICAgJ29uZScgICAgICAgPT4gJzEnLAogICAgICAgICAgICAndHdvJyAgICAgICA9PiAnMicsCiAgICAgICAgICAgICd0aHJlZScgICAgID0+ICczJywKICAgICAgICAgICAgJ2ZvdXInICAgICAgPT4gJzQnLAogICAgICAgICAgICAnZml2ZScgICAgICA9PiAnNScsCiAgICAgICAgICAgICdzaXgnICAgICAgID0+ICc2JywKICAgICAgICAgICAgJ3NldmVuJyAgICAgPT4gJzcnLAogICAgICAgICAgICAnZWlnaHQnICAgICA9PiAnOCcsCiAgICAgICAgICAgICduaW5lJyAgICAgID0+ICc5JywKICAgICAgICAgICAgJ3RlbicgICAgICAgPT4gJzEwJywKICAgICAgICAgICAgJ2VsZXZlbicgICAgPT4gJzExJywKICAgICAgICAgICAgJ3R3ZWx2ZScgICAgPT4gJzEyJywKICAgICAgICAgICAgJ3RoaXJ0ZWVuJyAgPT4gJzEzJywKICAgICAgICAgICAgJ2ZvdXJ0ZWVuJyAgPT4gJzE0JywKICAgICAgICAgICAgJ2ZpZnRlZW4nICAgPT4gJzE1JywKICAgICAgICAgICAgJ3NpeHRlZW4nICAgPT4gJzE2JywKICAgICAgICAgICAgJ3NldmVudGVlbicgPT4gJzE3JywKICAgICAgICAgICAgJ2VpZ2h0ZWVuJyAgPT4gJzE4JywKICAgICAgICAgICAgJ25pbmV0ZWVuJyAgPT4gJzE5JywKICAgICAgICAgICAgJ3R3ZW50eScgICAgPT4gJzIwJywKICAgICAgICAgICAgJ3RoaXJ0eScgICAgPT4gJzMwJywKICAgICAgICAgICAgJ2ZvcnR5JyAgICAgPT4gJzQwJywKICAgICAgICAgICAgJ2ZvdXJ0eScgICAgPT4gJzQwJywgLy8gY29tbW9uIG1pc3NwZWxsaW5nCiAgICAgICAgICAgICdmaWZ0eScgICAgID0+ICc1MCcsCiAgICAgICAgICAgICdzaXh0eScgICAgID0+ICc2MCcsCiAgICAgICAgICAgICdzZXZlbnR5JyAgID0+ICc3MCcsCiAgICAgICAgICAgICdlaWdodHknICAgID0+ICc4MCcsCiAgICAgICAgICAgICduaW5ldHknICAgID0+ICc5MCcsCiAgICAgICAgICAgICdodW5kcmVkJyAgID0+ICcxMDAnLAogICAgICAgICAgICAndGhvdXNhbmQnICA9PiAnMTAwMCcsCiAgICAgICAgICAgICdtaWxsaW9uJyAgID0+ICcxMDAwMDAwJywKICAgICAgICAgICAgJ2JpbGxpb24nICAgPT4gJzEwMDAwMDAwMDAnLAogICAgICAgICAgICAnYW5kJyAgICAgICA9PiAnJywKICAgICAgICApCiAgICApOwoKICAgIC8vIENvZXJjZSBhbGwgdG9rZW5zIHRvIG51bWJlcnMKICAgICRwYXJ0cyA9IGFycmF5X21hcCgKICAgICAgICBmdW5jdGlvbiAoJHZhbCkgewogICAgICAgICAgICByZXR1cm4gZmxvYXR2YWwoJHZhbCk7CiAgICAgICAgfSwKICAgICAgICBwcmVnX3NwbGl0KCcvW1xzLV0rLycsICRkYXRhKQogICAgKTsKCiAgICAkc3RhY2sgPSBuZXcgU3BsU3RhY2s7IC8vIEN1cnJlbnQgd29yayBzdGFjawogICAgJHN1bSAgID0gMDsgLy8gUnVubmluZyB0b3RhbAogICAgJGxhc3QgID0gbnVsbDsKCiAgICBmb3JlYWNoICgkcGFydHMgYXMgJHBhcnQpIHsKICAgICAgICBpZiAoISRzdGFjay0+aXNFbXB0eSgpKSB7CiAgICAgICAgICAgIC8vIFdlJ3JlIHBhcnQgd2F5IHRocm91Z2ggYSBwaHJhc2UKICAgICAgICAgICAgaWYgKCRzdGFjay0+dG9wKCkgPiAkcGFydCkgewogICAgICAgICAgICAgICAgLy8gRGVjcmVhc2luZyBzdGVwLCBlLmcuIGZyb20gaHVuZHJlZHMgdG8gb25lcwogICAgICAgICAgICAgICAgaWYgKCRsYXN0ID49IDEwMDApIHsKICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSBkcm9wIGZyb20gbW9yZSB0aGFuIDEwMDAgdGhlbiB3ZSd2ZSBmaW5pc2hlZCB0aGUgcGhyYXNlCiAgICAgICAgICAgICAgICAgICAgJHN1bSArPSAkc3RhY2stPnBvcCgpOwogICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYSBuZXcgcGhyYXNlCiAgICAgICAgICAgICAgICAgICAgJHN0YWNrLT5wdXNoKCRwYXJ0KTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgLy8gRHJvcCBkb3duIGZyb20gbGVzcyB0aGFuIDEwMDAsIGp1c3QgYWRkaXRpb24KICAgICAgICAgICAgICAgICAgICAvLyBlLmcuICJzZXZlbnR5IG9uZSIgLT4gIjcwIDEiIC0+ICI3MCArIDEiCiAgICAgICAgICAgICAgICAgICAgJHN0YWNrLT5wdXNoKCRzdGFjay0+cG9wKCkgKyAkcGFydCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAvLyBJbmNyZWFzaW5nIHN0ZXAsIGUuZyBvbmVzIHRvIGh1bmRyZWRzCiAgICAgICAgICAgICAgICAkc3RhY2stPnB1c2goJHN0YWNrLT5wb3AoKSAqICRwYXJ0KTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYSBuZXcgcGhyYXNlCiAgICAgICAgICAgICRzdGFjay0+cHVzaCgkcGFydCk7CiAgICAgICAgfQoKICAgICAgICAvLyBTdG9yZSB0aGUgbGFzdCBwcm9jZXNzZWQgcGFydAogICAgICAgICRsYXN0ID0gJHBhcnQ7CiAgICB9CgogICAgcmV0dXJuICRzdW0gKyAkc3RhY2stPnBvcCgpOwp9CgovLyB0ZXN0CiR3b3JkcyA9ICdmaXZlJzsKZWNobyB3b3Jkc190b19udW1iZXIoJHdvcmRzKTs=