Last active
October 30, 2017 16:50
-
-
Save littlefuntik/5b6970fdbaba0755a4c3417d514e06c1 to your computer and use it in GitHub Desktop.
Python function permutations in PHP language.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require 'permutations.php'; | |
$timeStart = microtime(true); | |
$memoryStart = memory_get_usage(); | |
$i = 0; | |
foreach (permutations(range(1, 3), 2) as $combo) { | |
echo json_encode($combo) . PHP_EOL; | |
++$i; | |
} | |
$_timeSeconds = microtime(true) - $timeStart; | |
$_memoryUsageMb = (memory_get_usage() - $memoryStart) / 1024 / 1024; | |
echo 'Total count: ' . $i . PHP_EOL; | |
echo 'Time seconds, s: ' . $_timeSeconds . PHP_EOL; | |
echo 'Memory usage, M: ' . $_memoryUsageMb . PHP_EOL; | |
die; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function py_range($start, $stop = null, $step = null) | |
{ | |
if (null === $stop) { | |
$stop = $start; | |
$start = 0; | |
} | |
if (null === $step) { | |
if ($start > $stop) { | |
return []; | |
} | |
--$stop; | |
return range($start, $stop); | |
} elseif (-1 === $step) { | |
if ($start > $stop) { | |
list($start, $stop) = [$stop, $start]; | |
} | |
++$start; | |
return array_reverse(range($start, $stop)); | |
} else { | |
if ($start > $stop) { | |
return []; | |
} | |
return range($start, $stop, $step); | |
} | |
} | |
/** | |
* Return successive r length permutations of elements in the iterable. | |
* | |
* If r is not specified or is None, then r defaults to the length of the iterable and all possible full-length permutations are generated. | |
* | |
* Permutations are emitted in lexicographic sort order. So, if the input iterable is sorted, the permutation tuples will be produced in sorted order. | |
* | |
* Elements are treated as unique based on their position, not on their value. So if the input elements are unique, there will be no repeat values in each permutation. | |
* | |
* Example usage, | |
* | |
* ```php | |
* $i = 0; | |
* foreach (permutations(range(1, 3), 2) as $combo) { | |
* echo json_encode($combo) . "\n"; | |
* ++$i; | |
* } | |
* echo 'Total count: ' . $i . "\n"; | |
* ``` | |
* | |
* Outputs, | |
* | |
* ``` | |
* [1,2] | |
* [1,3] | |
* [2,1] | |
* [2,3] | |
* [3,1] | |
* [3,2] | |
* Total count: 6 | |
* ``` | |
* | |
* @link https://docs.python.org/3/library/itertools.html#itertools.permutations itertools.permutations (source) | |
* | |
* @param array $pool | |
* @param null|int $r | |
* | |
* @return \Generator | |
*/ | |
function permutations($pool, $r = null) | |
{ | |
$n = count($pool); | |
$r = (null === $r) ? $n : $r; | |
if ($r <= $n) { | |
$indices = py_range($n); | |
$cycles = py_range($n, $n - $r, -1); | |
$ret = []; | |
foreach (array_slice($indices, 0, $r) as $i) { | |
$ret[] = $pool[$i]; | |
unset($i); | |
} | |
yield $ret; | |
while ($n) { | |
$isDone = true; | |
foreach (array_reverse(py_range($r)) as $i) { | |
$cycles[$i] -= 1; | |
if (0 === $cycles[$i]) { | |
$indices = array_merge( | |
array_slice($indices, 0, $i), | |
array_merge( | |
array_slice($indices, $i + 1), | |
array_slice($indices, $i, 1) | |
) | |
); | |
$cycles[$i] = $n - $i; | |
} else { | |
$j = $cycles[$i]; | |
// swap array values: $i and $tmpKey | |
$tmpValue = $indices[$i]; | |
$tmpKey = count($indices) - $j; | |
$indices[$i] = $indices[$tmpKey]; | |
$indices[$tmpKey] = $tmpValue; | |
unset($tmp, $y); | |
$ret = []; | |
foreach (array_slice($indices, 0, $r) as $i0) { | |
$ret[] = $pool[$i0]; | |
} | |
yield $ret; | |
$isDone = false; | |
break; | |
} | |
} | |
if ($isDone) { | |
break; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment