3

Suppose an array is

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
)

I want to call a function by providing two params (both arrays) with following permutations -

array(1) and array(2,3,4)
array(1,2) and array(3,4)
array(1,2,3) and array (4)
array(1,3) and array(2,4)
array(1,4) and array(2,3)
array(2) and array(1,3,4)
and so on...

Of course the actual arrays will be larger.

3
  • 6
    So you want to call a function, passing in those arrays, what are you expecting the result to be? Please show example input and output. Commented Apr 13, 2012 at 16:52
  • 1
    Those look more like equivalence classes than permutations Commented Apr 13, 2012 at 16:52
  • 3
    Check this : PHP code to generate all the combinations of a set of elements Commented Apr 13, 2012 at 17:13

3 Answers 3

2

I don't know how that "permutation" is called (it's not a permutation even probably), but it looked promising to me exploiting the fact that the elements in the set are ordered (if not, there is the order of index, so use index instead of value) so to shift from right to left and combine all left with right combinations.

This is either possible with recursion or with a stack, I normally prefer the stack.

The usage as suggested (encapsulating the function call):

$funky = function($a, $b) {
    printf("(%s) and (%s)\n", implode(',', $a), implode(',', $b));
};

$paired = function($function) {
    return function(array $array) use ($function) {
        ...
    };
};


$funkyAll = $paired($funky);
$funkyAll(range(1, 5));

Running this with a sorted (more memory required) stack consuming strategy gives the following output (formatted in columns):

(1) and (2,3,4,5)    (2,4) and (1,3,5)    (1,4,5) and (2,3)
(2) and (1,3,4,5)    (2,5) and (1,3,4)    (2,3,4) and (1,5)
(3) and (1,2,4,5)    (3,4) and (1,2,5)    (2,3,5) and (1,4)
(4) and (1,2,3,5)    (3,5) and (1,2,4)    (2,4,5) and (1,3)
(5) and (1,2,3,4)    (4,5) and (1,2,3)    (3,4,5) and (1,2)
(1,2) and (3,4,5)    (1,2,3) and (4,5)    (1,2,3,4) and (5)
(1,3) and (2,4,5)    (1,2,4) and (3,5)    (1,2,3,5) and (4)
(1,4) and (2,3,5)    (1,2,5) and (3,4)    (1,2,4,5) and (3)
(1,5) and (2,3,4)    (1,3,4) and (2,5)    (1,3,4,5) and (2)
(2,3) and (1,4,5)    (1,3,5) and (2,4)    (2,3,4,5) and (1)

The exemplary implementation (full source-code as gist) is memory optimized and produces this order (array_pop instead of array_shift):

(1) and (2,3,4,5)    (2,4) and (1,3,5)    (1,4,5) and (2,3)
(2) and (1,3,4,5)    (2,5) and (1,3,4)    (1,3,4) and (2,5)
(3) and (1,2,4,5)    (2,4,5) and (1,3)    (1,3,5) and (2,4)
(4) and (1,2,3,5)    (2,3,4) and (1,5)    (1,3,4,5) and (2)
(5) and (1,2,3,4)    (2,3,5) and (1,4)    (1,2,3) and (4,5)
(4,5) and (1,2,3)    (2,3,4,5) and (1)    (1,2,4) and (3,5)
(3,4) and (1,2,5)    (1,2) and (3,4,5)    (1,2,5) and (3,4)
(3,5) and (1,2,4)    (1,3) and (2,4,5)    (1,2,4,5) and (3)
(3,4,5) and (1,2)    (1,4) and (2,3,5)    (1,2,3,4) and (5)
(2,3) and (1,4,5)    (1,5) and (2,3,4)    (1,2,3,5) and (4)

Implementation:

$stack[] = array(array(), $array);
while (list($left, $right) = array_pop($stack)) {
    $min = end($left);
    foreach ($right as $value)
    {
        if ($value < $min) continue;
        $left2 = array_merge($left, array($value));
        $right2 = array_diff($right, $left2);
        if (!($left2 && $count = count($right2))) continue;
        $function($left2, $right2);
        --$count && $stack[] = array($left2, $right2);
    }
}

I hope this is useful.

Another array related algorithm: Sorting with a modulus (just for reference, while writing this one I was reminded to that matrix thing)

Sign up to request clarification or add additional context in comments.

1 Comment

1

how about using array_pop with array_merge

chk this url

http://php.net/manual/en/function.array-pop.php

and use sarafov's suggestion with the url

http://www.sonyjose.in/blog/?p=62

something like

foreach($combinations as $combination)
    while(in_array($combination)){
        $arr = array_pop($combination);
        foo($fruit , $combination); 
    }
}

Comments

1

I think this is what you need.

Code :

<?php

function combinations($arr, $n)
{
    $res = array();

    foreach ($arr[$n] as $item)
    {
        if ($n==count($arr)-1)
            $res[]=$item;
        else
        {
            $combs = combinations($arr,$n+1);

            foreach ($combs as $comb)
            {
                $res[] = "$item $comb";
            }
        }
    }
    return $res;
}

// Your ARRAY
//
// you can put as many items in each subarray as you like... 
// and as many subarrays as you like
$words = array(array('A','B'),array('C','D'), array('E','F'));

$combos = combinations($words,0);  // ALWAYS, call it with 0 as the last parameter
print_r($combos);

?>

Output :

Array
(
    [0] => A C E
    [1] => A C F
    [2] => A D E
    [3] => A D F
    [4] => B C E
    [5] => B C F
    [6] => B D E
    [7] => B D F
)

Usage : (like in your example)

$combos = combinations(array(array(1,4),array(2,3)));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.