eight / solution 8.3
<?php
function numbersToWords(string $t)
{
return preg_replace_callback("/[\$]?-?\d+([,\s]?\d{3,})*/", "numberToWords", $t);
}
function numberToWords(array $n)
{
$n = $n[0];
// check for dollar amount
$dollars = str_contains($n, "$");
$n = str_replace("$", "", $n);
// no need to process anything else if it's just 0
if ($n == "0") {
return "zero";
}
$n = str_replace([",", " "], "", $n) + 0;
// keep track of whether it's a negative number
$n < 0 ? ($n *= -1) && ($negative = true) : ($negative = false);
$n = $n . "";
$a = [];
// break number into three-digit blocks for processing
for ($i = 3; $i >= 0; $i--) {
$a[$i] = substr($n, -3);
$n = substr($n, 0, -3);
}
foreach ($a as &$i) {
strlen($i) && ($i = numberBlockToWords($i));
}
$build = $negative ? "negative " : "";
strlen($a[0]) && ($build .= " " . $a[0] . " billion ");
strlen($a[1]) && ($build .= " " . $a[1] . " million ");
strlen($a[2]) && ($build .= " " . $a[2] . " thousand ");
strlen($a[3]) && ($build .= " " . $a[3] . " ");
if ($dollars) {
// this might look wrong in context but it's a good general application
$build = trim($build) == "one" ? $build . " dollar " : $build . " dollars ";
}
return trim(preg_replace("/\s+/", " ", $build));
}
function numberBlockToWords(string $n)
{
$a = [];
for ($i = 2; $i >= 0; $i--) {
$a[$i] = substr($n, -1);
strlen($a[$i]) && ($a[$i] += 0);
$n = substr($n, 0, -1);
}
$build = "";
is_int($a[0]) && $a[0] > 0 && ($build .= " " . numberOnesToWords($a[0]) . " hundred ");
is_int($a[1]) && $a[1] >= 2 && ($build .= " " . numberTensToWords($a[1]) . " ");
is_int($a[1]) && $a[1] == 1 && ($a[2] += 10);
is_int($a[2]) && $a[2] > 0 && ($build .= " " . numberOnesToWords($a[2]) . " ");
return trim($build);
}
function numberOnesToWords(int $n)
{
switch ($n) {
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";
}
}
function numberTensToWords(int $n)
{
switch ($n) {
case 2:
return "twenty";
case 3:
return "thirty";
case 4:
return "forty";
case 5:
return "fifty";
case 6:
return "sixty";
case 7:
return "seventy";
case 8:
return "eighty";
case 9:
return "ninety";
}
}
$inputText = "is 100,987,000,423 a large number or no more significant than 42?";
$outputText = numbersToWords($inputText);
print_r($outputText . "\n\n");