Skip to content

Instantly share code, notes, and snippets.

@bagart
Created November 3, 2018 00:07
Show Gist options
  • Save bagart/e97b6498217d0903d999b1cc8e58783b to your computer and use it in GitHub Desktop.
Save bagart/e97b6498217d0903d999b1cc8e58783b to your computer and use it in GitHub Desktop.
<?php
function dont_give_me_five(int $start, int $end): int
{
$start_multiple = $start < 0 ? -1 : 1;
$end_multiple = $end < 0 ? -1 : 1;
$zero_value = (int)(
$start_multiple !== $end_multiple
|| false === strpos((string)min(abs($start), abs($end)), '5')
);
if ($start == $end) {
return $zero_value;
}
return (
abs(
five_0_to_num(abs($start)) * $start_multiple
- five_0_to_num(abs($end)) * $end_multiple
)
+ $zero_value
);
}
function five_0_to_num(int $value): int
{
assert($value >= 0, 'Optimization: abs first');
if (!$value) {
return 0;
}
$string = (string)$value;
if ($string[0] == 5) {
$string = '4' . str_repeat('9', strlen($string) - 1);
$value = (int)$string;
}
$last = ($string[0] - ($string[0] > 4 ? 1 : 0)) * pow(9, strlen($string) - 1);
return $last + five_0_to_num((int)mb_substr($value, 1));
}
/**
* class DontGiveMeFiveTest extends TestCase {
* public function testSimple()
* {
* $this->assertEquals(8, dont_give_me_five(1, 9));
* $this->assertEquals(12, dont_give_me_five(4, 17));
* }
*
* public function testWithEthalon()
* {
* $test_array = [0, 1, 5, 105, 150, 500, 555, 444, 446, 600, 99999];
* foreach ($test_array as $xx) {
* foreach ([-1, 1] as $xm) {
* $x = $xx * $xm;
* foreach ($test_array as $yy) {
* foreach ([-1, 1] as $ym) {
* $y = $yy * $ym;
*
* $this->assertEquals(
* $this->ethalon($x, $y),
* dont_give_me_five($x, $y),
* "$x => $y with: " . $this->ethalon($x, $y) . '!='. dont_give_me_five($x, $y)
* );
* }
* }
* }
* }
*
* $this->assertEquals(
* 2477039237406838187,
* dont_give_me_five(PHP_INT_MIN + 1, PHP_INT_MAX - 1),
* 'PHP_INT_MIN => PHP_INT_MAX'
* );
* }
*
* public function testTime()
* {
*
* $microtime1 = microtime(true);
* $my_result = dont_give_me_five(PHP_INT_MIN + 1, PHP_INT_MAX - 1);
* $microtime2 = microtime(true);
* var_dump([
* "my" => [
* 'value' => $my_result,
* 'time' => ceil(($microtime2 - $microtime1)*10000)/10000,
* ]
* ]);
*
* $microtime3 = microtime(true);
* $ethalon_result = $this->ethalon(PHP_INT_MIN + 1, PHP_INT_MAX - 1);
* $microtime4 = microtime(true);
*
* var_dump([
* "ethalon" => [
* 'value' => $my_result === $ethalon_result,
* 'diff' => ceil(($microtime4-$microtime3) - ($microtime2-$microtime1))/1000 .'s',
* ],
* ]);
* }
*
*
* public function ethalon(int $start, int $end):int
* {
* if ($start > $end) {
* list($start, $end) = [$end, $start];
* }
* $count = 0;
* for ($x = $start; $x <= $end; ++$x) {
* if (strpos($x, '5') === false) {
* $count++;
* }
* }
*
* return $count;
* }
* }
*/
$test_array = [0, 1, 5, 105, 150, 500, 555, 444, 446, 600, 99999];
foreach ($test_array as $xx) {
foreach ([-1, 1] as $xm) {
$x = $xx * $xm;
foreach ($test_array as $yy) {
foreach ([-1, 1] as $ym) {
$y = $yy * $ym;
$r = [
ethalon($x, $y),
dont_give_me_five($x, $y)
];
if ($r[0] != $r[1]) {
var_dump(["$x => $y" => $r]);
} else {
echo '.';
}
}
}
}
}
$microtime1 = microtime(true);
$my_result = dont_give_me_five(PHP_INT_MIN + 1, PHP_INT_MAX - 1);
$microtime2 = microtime(true);
var_dump([
"my" => [
'value' => $my_result,
'time' => ceil(($microtime2 - $microtime1) * 10000) / 10000,
]
]);
$microtime3 = microtime(true);
$ethalon_result = ethalon(PHP_INT_MIN + 1, PHP_INT_MAX - 1);
$microtime4 = microtime(true);
var_dump([
"ethalon" => [
'value' => $my_result === $ethalon_result,
'diff' => ceil(($microtime4 - $microtime3) - ($microtime2 - $microtime1)) / 1000 . 's',
],
]);
$microtime5 = microtime(true);
$ethalon2_result = ethalon2(PHP_INT_MIN + 1, PHP_INT_MAX - 1);
$microtime6 = microtime(true);
var_dump([
"ethalon" => [
'value' => $my_result === $ethalon2_result,
'diff' => ceil(($microtime6 - $microtime5) - ($microtime2 - $microtime1)) / 1000 . 's',
],
]);
function ethalon(int $start, int $end): int
{
if ($start > $end) {
list($start, $end) = [$end, $start];
}
$count = 0;
for ($x = $start; $x <= $end; ++$x) {
if (strpos($x, '5') === false) {
$count++;
}
}
return $count;
}
function ethalon2(int $start, int $end): int
{
return count(array_filter(range($start, $end), function ($iNumber) {
return strpos((string)$iNumber, '5') === false;
}));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment