seven / solution 7.4
<?php
divide([58743758, 71]);
function divide($n, $maxDecimals = 5)
{
// we'll use a global variable rather than passing one back and forth but that's an alternative approach
global $result;
// if we don't have any of our result built yet, initialize the variable as an empty string
!isset($result) && ($result = "");
print_r("dividing " . $n[0] . " by " . $n[1] . ".\n");
// instead of working with decimals, just add the maximum amount of decimals to the end of the numerator and round it to no decimal places
$top = round($n[0] * 10 ** $maxDecimals);
$bottom = $n[1];
// perform the recursive division
doDivision($top, $bottom);
// remove any extra decimal places then go back to decimal mode by dividing by the same number we multiplied by earlier to switch to integers
$result = round($result) / 10 ** $maxDecimals;
// if there are more decimal places in the real answer than we've calculated with long-division, let the user know
!($n[0] / $n[1] == $result) && print_r("ran out of decimal places.\n");
// output the result and return it
print_r($n[0] . " divided by " . $n[1] . " is " . $result . "\n");
return $result;
}
function doDivision($top, $bottom, $remainder = 0)
{
global $result;
// try dividing by the beginning of the numerator until the result is at least 1
for ($i = 1; $i <= strlen($top); $i++) {
// take $i digits from the beginning of the numerator (number of loops)
$tryTop = substr($top, 0, $i);
// check whether the denominator goes into the trial numerator at least once
if ($tryTop / $bottom >= 1) {
// round down
$times = floor($tryTop / $bottom);
// show how many times, making sure to use "once" instead of "1 times"
$timesString = $times == 1 ? "once" : $times . " times";
print_r($bottom . " goes into " . $tryTop + 0 . " " . $timesString);
// calculate remainder using remainder division and output it
$remainder = $tryTop % $bottom;
$remainder && print_r(" with " . $remainder . " remaining");
print_r(".\n");
// add number of times to the end of our built result
$result .= $times;
// take the loop number of digits from the numerator because we've already dealt with those
$top = substr($top, $i);
// add the remainder back to the beginning of the numerator
$remainder && ($top = $remainder . $top);
// pass the rest of the numerator to this function for another pass and let it know if there's a remainder because that means skip the leading zero
doDivision($top, $bottom, $remainder);
return;
} else {
// if it's less than once, add a zero to the result we're building for each digit in the denominator
// don't worry if it's at the beginning because leading zeros are trimmed from numeric values when we convert back
!$remainder && ($result .= str_repeat("0", strlen($bottom)));
}
}
}