Created
December 30, 2016 06:32
-
-
Save ronisaha/1d920c2cb6b18f79050bb9930b495b4d to your computer and use it in GitHub Desktop.
CombinationGenerator example
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 | |
| class CombinationGenerator implements \Iterator | |
| { | |
| private $array; | |
| private $length; | |
| private $itemCount; | |
| private $pos = -1; | |
| private $binArray = array(); | |
| private $cache = array(); | |
| function __construct(array $array, $length = 0) { | |
| $this->array = $array; | |
| $this->itemCount = count($array); | |
| $this->length = $length; | |
| if($length > $this->itemCount) { | |
| throw new \Exception("Cannot pick $length item from $this->itemCount"); | |
| } | |
| $this->init(); | |
| } | |
| private function init() { | |
| $this->buildBinaryArray(); | |
| $this->rewind(); | |
| } | |
| private function buildBinaryArray() { | |
| $binaryString = str_repeat(1, $this->itemCount); | |
| $max = bindec($binaryString); | |
| for ($i = $max; $i > 0; $i--) | |
| { | |
| if (substr_count(decbin($i), "1") == $this->length) | |
| { | |
| $this->binArray[] = str_split(str_pad(decbin($i), $this->itemCount, "0", STR_PAD_LEFT)); | |
| } | |
| } | |
| } | |
| function key() { | |
| return $this->pos; | |
| } | |
| function current() | |
| { | |
| if (!isset($this->binArray[$this->pos])) { | |
| return null; | |
| } | |
| if(!isset($this->cache[$this->pos])){ | |
| $this->createCache(); | |
| } | |
| return $this->cache[$this->pos]; | |
| } | |
| function next() { | |
| $this->pos++; | |
| } | |
| function rewind() { | |
| $this->pos = 0; | |
| } | |
| function valid() { | |
| return isset($this->binArray[$this->pos]); | |
| } | |
| private function createCache() | |
| { | |
| $this->cache[$this->pos] = array(); | |
| foreach ($this->binArray[$this->pos] as $indx => $digit) { | |
| if ($digit == '1') { | |
| $this->cache[$this->pos][] = $this->array[$indx]; | |
| } | |
| } | |
| } | |
| } | |
| class MaxSumFilterIterator extends \FilterIterator | |
| { | |
| private $maxSum = 0; | |
| public function __construct(Iterator $iterator , $maxSum ) | |
| { | |
| parent::__construct($iterator); | |
| $this->maxSum = $maxSum; | |
| } | |
| public function accept() | |
| { | |
| $array = $this->getInnerIterator()->current(); | |
| return (array_sum($array)) <= $this->maxSum; | |
| } | |
| } | |
| //Usages | |
| $array = ['1', '2', '3', '4', '5', '6', '7']; | |
| $allCombinations = new CombinationGenerator($array, 5); | |
| foreach($allCombinations as $key => $subSet){ | |
| echo ' ----- ' . $key . PHP_EOL; | |
| print_r($subSet); | |
| } | |
| $combinationWithMaxSum = new MaxSumFilterIterator($allCombinations, 16); | |
| foreach($combinationWithMaxSum as $key => $subSet){ | |
| echo ' ----- ' . $key . PHP_EOL; | |
| print_r($subSet); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment