-2

I have an array. This an example:

$array = ['A', 'B', 'C', 'D']

I would like all possible combination to get the following result:

$new_array = [
    ['A', 'B'], ['A', 'C'], ['A', 'D'],
    ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'C', 'D'],
    ['B', 'C'], ['B', 'D'],
    ['B', 'C', 'D']
    ['C', 'D']
['A', 'B', 'C', 'D']
]

So, as you can see, the result is a combination of array but they are all uniques. I mean ['A', 'B'] shoud be in the outpout but not ['B', 'A']. Also values in arrays should be sorted in alphanumeric order.

Unless I'm wrong, an array with 4 values gives 11 possibles and uniques combinations.

Thanks for your help.

Tidjy
  • 27
  • 4
  • Please share your attempts to resolve the problem. The linked question should already provide some first solutions. If any of them do not work as expected, please share more details – Nico Haase Jun 23 '23 at 14:01

2 Answers2

2

You need a power set of the given elements with the additional filters of removing individual elements.

So, for a collection of 4 elements, total 15 combinations are possible. For your case, we will have to remove 4 individual elements making it 11 different sets or combinations.

For every integer from 1 to 15, we keep including all the elements whose index comes in the binary representation of the current integer in iteration and add them to the result. If any integer has only 1 bit set(meaning being a power of 2), it means it is an individual element and we simply continue our loop skipping the processing part.

Finally, we use usort to sort the sets alphabetically and use strcmp to compare 2 different sets by converting them to strings using implode separated by | character to avoid any overlapping issues.

Snippet:

<?php
    
$payload = ['A', 'B', 'C', 'D'];

$total = (1 << count($payload)) - 1;

$result = [];

for($i = 1; $i <= $total; ++$i){
    if(($i & ($i - 1)) == 0) continue; // avoiding single items since you don't wish to have them
    $curr = [];
    for($j = 0; $j < count($payload); ++$j){
        if(($i & (1 << $j)) > 0){
            $curr[] = $payload[ $j ];
        }
    }
    $result[] = $curr;
}

usort($result, function($a, $b){
    return strcmp( implode("|", $a), implode("|", $b) );
});

print_r($result);

Online Demo

A.L
  • 10,259
  • 10
  • 67
  • 98
nice_dev
  • 17,053
  • 2
  • 21
  • 35
  • Thank you. The online demo works! But I misstated my request. In fact i need the collection of 4 elements too. [A, B, C, D]. – Tidjy Jun 23 '23 at 13:51
  • 1
    Okay, replace `$total = (1 << count($payload)) - 1;` by `$total = (1 << count($payload)) ;` did the job! Thank you again. – Tidjy Jun 23 '23 at 14:23
  • @Tidjy Glad to help. I didn't miss it, since you didn't include it in your question, I didn't either. Updated my answer now. – nice_dev Jun 23 '23 at 14:27
0
<?php
    
    $payload = ['a', 'b', 'c', 'd'];
    
    function permutations($payload) {
        if (empty($payload)) { 
            return [[]];
        }
    
        $results = [];
        foreach ($payload as $key => $value) {
            foreach (permutations(array_diff_key($payload, [$key => $value])) as $subarray) {
                $results[] = array_merge([$value], $subarray);
            }
        }
    
        return $results;
    }
    
    $permutations = array_map('implode', permutations($payload));
    print_r($permutations);
    
?>
fosterushka
  • 316
  • 2
  • 6
  • what framework do you use ? and what php version ? cuz i don;t like this solution due included foreach and you can avoided with php8.2 and make code more effecient; – fosterushka Jun 23 '23 at 11:10
  • It looks the OP want only 2 items in the output (AB), not 4 (ABCD). This code gives 4: https://3v4l.org/vQmXh – A.L Jun 23 '23 at 11:14
  • so if payload a,b,c,d output should be all combination among those payload letters ? like : ab, ac, ad, bc, bd ,cd and so on ..... correct ? – fosterushka Jun 23 '23 at 11:17
  • Yes that's the expected result shown in the question. – A.L Jun 23 '23 at 11:20
  • in question you had 3 as well but anyway this is 2 item output https://3v4l.org/lgpeD – fosterushka Jun 23 '23 at 11:26
  • My bad, you're right, the question asked for permutations with 2 and 3 items. – A.L Jun 23 '23 at 11:42
  • This is incorrect. OP needs all combinations not all permutations of 4 elements. You don't seem to show any demo of how this can be achieved. Avoid adding half baked answers! – nice_dev Jun 23 '23 at 12:31
  • I just edited my question. So, all possibles combinations are: ['A', 'B'], ['A', 'C'], ['A', 'D'], ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'C', 'D'], ['B', 'C'], ['B', 'D'], ['B', 'C', 'D'] ['C', 'D'] ['A', 'B', 'C', 'D'] The above solution it's not working because output returns: ['A', 'B', 'C', 'D'], ['A', 'C', 'D', 'B'], ['B', 'C', 'A', 'D'] ... – Tidjy Jun 23 '23 at 13:43