<?php
/**
* Permutator
*
* A functional class to perform tasks on each permutation of an array.
*
* @version 0.01
* @author Shannon Wynter (http://fremnet.net/contact)
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @copyright Copyright (c) 2010, Shannon Wynter
*/
class Permutator {
/**
* Storage for the original array passed to the constructor
* @var array
*/
private $source_array;
/**
* Storage for any valid callback (see {@link http://www.php.net/callback#callback PHP documentation})
* @var callback
*/
private $callback_function;
/**
* Storage for any arguments to pass to the callback if any
* @var mixed
*/
private $callback_argument;
/**
* Class constructor
*
* When calling the callback function the call is
* $callback_function($permutation, $callback_argument)
*
* @param array $source_array Array to permutate
* @param callback $callback_function The function to call
* @param mixed $callback_argument This parameter is passed to the callback function as the second argument
*/
public function __construct($source_array, $callback_function, $callback_argument = null) {
$this->source_array = $source_array;
$this->callback_function = $callback_function;
$this->callback_argument = $callback_argument;
}
/**
* Factors
*
* Get the number of factors
*
* @return integer
*/
public function factors() {
return $this->factorial(count($this->source_array));
}
/**
* Process
*
* Begin permutating the array
*/
public function process() {
$this->permutation($this->source_array);
}
/**
* Factorial
*
* Calculate the factorial of a given number
*
* @param integer $number
* @return integer
*/
private function factorial($number) {
if ($number == 0) return 1;
return $number * $this->factorial($number - 1);
}
/**
* Permutation
*
* Recursive function to find the permutations and eventually call
* the callback function wrapper with the current permutation
*
* @param array $items
* @param integer $depth
* @param array $current
*/
private function permutation($items, $depth = 0, $current = array()) {
$count = count($items);
if ($count == 0) {
call_user_func($this->callback_function, $current, $this->callback_argument);
}
else {
for ($i = 0; $i < $count; $i ++) {
$new_items = $items;
$current[$depth] = reset(array_splice($new_items, $i, 1));
$this->permutation($new_items, $depth + 1, $current);
}
}
}
}