Search code examples
phpfor-loopcombinationspermutation

How to get all the combinations of an array in php without functions


hope all of you are doing ok. I'm having a problem with this, because I'm looking for a way to get all the combinations of an array of numbers, but I want to do it without any function, I don't think that's possible, all the answers I already saw on internet have some function or method to do that.

I try this, give this array:

$numbers=[1,2,3,4];

I built 4 for loops to take the position of the array, and create a number, but, it supposes to be 24 different combinations give that array, with my for loops I get 256 combination

for($i = 0; $i <= 3; $i++){
for($j = 0; $j <= 3;$j++){
        for($k = 0;$k <= 3;$k++){
            for($l = 0; $l <= 3;$l++){
                 echo "$numbers[$i]$numbers[$j]$numbers[$k]$numbers[$l] <br>";
             }
         }
     } 
} 
>echo "Combinations: $contador \n";

Could someone please help me! (I want to get the combination on a new array per value, to compare later with a random number)


Solution

  • Getting all combinations works on the principle of next permutation. This basically means it follows the below steps:

    • The input needs to be sorted as the starting combination. This eases out the calculations and produces a uniform result. Below snippet does use sort() inbuilt function but you can roll out for your own sort function(which I leave it to you as an exercise).

    • For a next permutation, we need to find 2 digits where smaller digit occupies an MSB place over the larger digit.

    • Once found, we swap those 2 digits and reverse the array from MSB + 1 position. This reverse operation is to get next smallest lexicographic combination. If not performed, you will miss out on some needed in-between combinations.

    • The logic stops when the digits get sorted in non-increasing manner yielding the last combination possible.

    Snippet:

    <?php
    
    function getCombinations($numbers){
      sort($numbers); // create your own custom function for sort.
      $result = [ $numbers ];
      do{
        $x = $y = -1;
        
        for($i = count($numbers) - 1; $i >= 0; --$i){
          for($j = $i - 1; $j >= 0; --$j){
            if($numbers[ $j ] < $numbers[ $i ] && ($y === -1 || $y < $j)){
              $x = $i;
              $y = $j;
            }
          }
        }
        
        if($x !== -1){
          swap($numbers, $x, $y);
          reverse($numbers, $y + 1, count($numbers) - 1);
          $result[] = $numbers;
        }
      }while($x != -1);
      
      return $result;
    }
    
    function reverse(&$numbers, $left, $right){
      while($left < $right){
        swap($numbers, $left++, $right--);
      }
    }
    
    function swap(&$numbers, $x, $y){
      $temp = $numbers[ $x ];
      $numbers[ $x ] = $numbers[ $y ];
      $numbers[ $y ] = $temp;
    }
    
    
    print_r(getCombinations([1,2,3,4]));
    

    Online Demo