phparrayspermute

Permutation and Combination in PhP


I I want to compute the permutations 5p2, 5p3, 5p4 and 5p5 from the array [1,2,3,4,5] The function below only runs 5p5. To run 5p2, 5p3, 5p4 I will have to manually iterate through the array using a for...loop. Please help me.

//function to return permutations 5p5 array
        function combinationArray($myarr) {
            $results = [];
            $current = [];
            $next = function($myarr) use(&$next,&$results,&$current) {
                $l = count($myarr);
                if($l === 1) {
                    $current []= $myarr[0];
                    $results []= intval(implode($current)); //use this for array containing numbers only
                    //$results []= implode($current); //use this for array containing alphabets
                    array_pop($current);
                    return;
                }
                for($i=0; $i<$l; $i++) {
                    $tmpArr = $myarr;
                    $current []= array_splice($tmpArr,$i,1)[0];
                    $next($tmpArr);
                    array_pop($current);
                }
            };
            $next($myarr);
            return $results;
        }

//Manual iteration of 5c2 will be like this....about 120 different modules.....

$wordArray = str_split($sWord, 1);
$newArray1 = $wordArray[0]; $newArray2 = $wordArray[1];$newArray3 = $wordArray[2]; $newArray4 = $wordArray[3]; $newArray5 = $wordArray[4]; 
    //12
for($a = 0; $a < count($newArray1); $a++){
    for($b = 0; $b < count($newArray2); $b++){
        $aux = $newArray1[$a].$newArray2[$b]; array_push($result52, $aux);                              
    }
}
//13
for($a = 0; $a < count($newArray1); $a++){
    for($c = 0; $c < count($newArray3); $c++){
        $aux = $newArray1[$a].$newArray3[$c]; array_push($result52, $aux);                              
    }
}
//14
for($a = 0; $a < count($newArray1); $a++){
    for($d = 0; $d < count($newArray4); $d++){
        $aux = $newArray1[$a].$newArray4[$d]; array_push($result52, $aux);                              
    }
}
//15
for($a = 0; $a < count($newArray1); $a++){
    for($e = 0; $e < count($newArray5); $e++){
        $aux = $newArray1[$a].$newArray5[$e]; array_push($result52, $aux);                              
    }
}
//21
for($b = 0; $b < count($newArray2); $b++){
    for($a = 0; $a < count($newArray1); $a++){      
        $aux = $newArray2[$b].$newArray1[$a]; array_push($result52, $aux);                              
    }
}
//23
for($b = 0; $b < count($newArray2); $b++){
    for($c = 0; $c < count($newArray3); $c++){      
        $aux = $newArray2[$b].$newArray3[$c]; array_push($result52, $aux);                              
    }
}
//24
for($b = 0; $b < count($newArray2); $b++){
    for($d = 0; $d < count($newArray4); $d++){      
        $aux = $newArray2[$b].$newArray4[$d]; array_push($result52, $aux);                              
    }
}
//25
for($b = 0; $b < count($newArray2); $b++){
    for($e = 0; $e < count($newArray5); $e++){  
        $aux = $newArray2[$b].$newArray5[$e]; array_push($result52, $aux);                              
    }
}
//31
for($c = 0; $c < count($newArray3); $c++){
    for($a = 0; $a < count($newArray1); $a++){
        $aux = $newArray3[$c].$newArray1[$a]; array_push($result52, $aux);                              
    }
}
//32
for($c = 0; $c < count($newArray3); $c++){
    for($b = 0; $b < count($newArray2); $b++){
        $aux = $newArray3[$c].$newArray2[$b]; array_push($result52, $aux);                              
    }
}
//34
for($c = 0; $c < count($newArray3); $c++){
    for($d = 0; $d < count($newArray4); $d++){
        $aux = $newArray3[$c].$newArray4[$d]; array_push($result52, $aux);                              
    }
}
//35
for($c = 0; $c < count($newArray3); $c++){
    for($e = 0; $e < count($newArray5); $e++){
        $aux = $newArray3[$c].$newArray5[$e]; array_push($result52, $aux);                              
    }
}
//41
for($d = 0; $d < count($newArray4); $d++){
    for($a = 0; $a < count($newArray1); $a++){
        $aux = $newArray4[$d].$newArray1[$a]; array_push($result52, $aux);                              
    }
}
//42
for($d = 0; $d < count($newArray4); $d++){
    for($b = 0; $b < count($newArray2); $b++){
        $aux = $newArray4[$d].$newArray2[$b]; array_push($result52, $aux);                              
    }
}
//43
for($d = 0; $d < count($newArray4); $d++){
    for($c = 0; $c < count($newArray3); $c++){
        $aux = $newArray4[$d].$newArray3[$c]; array_push($result52, $aux);                              
    }
}
//45
for($d = 0; $d < count($newArray4); $d++){
    for($e = 0; $e < count($newArray5); $e++){
        $aux = $newArray4[$d].$newArray5[$e]; array_push($result52, $aux);                              
    }
}
//51
for($e = 0; $e < count($newArray5); $e++){
    for($a = 0; $a < count($newArray1); $a++){
        $aux = $newArray5[$e].$newArray1[$a]; array_push($result52, $aux);                              
    }
}
//52
for($e = 0; $e < count($newArray5); $e++){
    for($b = 0; $b < count($newArray2); $b++){
        $aux = $newArray5[$e].$newArray2[$b]; array_push($result52, $aux);                              
    }
}
//53
for($e = 0; $e < count($newArray5); $e++){
    for($c = 0; $c < count($newArray3); $c++){
        $aux = $newArray5[$e].$newArray3[$c]; array_push($result52, $aux);                              
    }
}
//54
for($e = 0; $e < count($newArray5); $e++){
    for($d = 0; $d < count($newArray4); $d++){
        $aux = $newArray5[$e].$newArray4[$d]; array_push($result52, $aux);                              
    }
}

$result52 = array_unique($result52); //remove duplicates... but the indexes dont align.
$result52 = array_reduce($result52,"myfunction");//convert the array into a string bcos of the indexes              
$result52 = str_split($result52, 2); //split the new string in twos into an array to get correct indexes
print_r($result52);

Thank you all.


Solution

  • I fished some things in the internet. I hope this suits your needs.

    I don't take any credit for this. It's a combination of these two solutions: Generating a Power Set and Implementing Heap's Algorithm

    <?php
    
    $arr1 = [1,2,3];
    
    /**
     * Permutation.
     */
    class Permutation
    {
        /**
         * @var array
         */
        protected $items;
    
        /**
         * @var array
         */
        protected $result = [];
    
        /**
         * @param array $array
         * @param int   $permutation
         */
        public function __construct($array, $permutation)
        {
            if (count($array) < $permutation) {
                throw new Exception("That's impossible for me :/");
            }
    
            // first get all the unique subsets with the permutation's length
            $subsets = $this->getPowerSet($array, $permutation);
    
            // genereate the permutation for each subset
            foreach ($subsets as $subset) {
                $this->setItems($subset)->heaps($this->n, $this->items);
            }
    
            sort($this->result);
        }
    
        /**
         * Get result.
         *
         * @return array
         */
        public function getResult()
        {
            return $this->result;
        }
    
        /**
         * Set items.
         *
         * @param array $items
         */
        public function setItems($items)
        {
            $this->items = $items;
            $this->n = count($items);
            return $this;
        }
    
        private function swap(&$items, $i, $j)
        {
            $temp = $items[$i];
            $items[$i] = $items[$j];
            $items[$j] = $temp;
        }
    
        /**
         * This is Heap's algorithm, generates all possible permutations of n items.
         *
         * @link https://en.wikipedia.org/wiki/Heap%27s_algorithm
         *
         * @param int   $n
         * @param array $items
         */
        private function heaps($n, &$items)
        {
            if ($n == 1) {
                $this->result[] = implode('', $items);
            } else {
                for ($i = 0; $i < $n; ++$i) {
                    $this->heaps($n - 1, $items);
                    if ($n % 2 == 0) {
                        $this->swap($items, 0, $n - 1);
                    } else {
                        $this->swap($items, $i, $n - 1);
                    }
                }
            }
        }
    
        /**
         * Way to get the Power Set (set of all unique subsets)
         * 
         * @link https://www.php.net/manual/en/function.shuffle.php#88408
         * 
         * @param array $in
         * @param int   $length
         */
        private function getPowerSet($in, $length) {
            $count = count($in);
            $members = pow(2,$count);
            $return = array();
            for ($i = 0; $i < $members; $i++) {
                $b = sprintf("%0".$count."b",$i);
                $out = array();
                for ($j = 0; $j < $count; $j++) {
                    if ($b{$j} == '1') $out[] = $in[$j];
                }
                if (count($out) === $length) {
                    $return[] = $out;
                }
            }
            return $return;
        }
    }
    
    $permutation = new Permutation($arr1, 2);
    
    echo "<pre>";
    print_r($permutation->getResult());
    echo "</pre>";