-1

I have an array that looks like this: [0, 1, 2, 3, 4, 5, ...]

I need a function that will give me an array like this:

[
[[0, 1, 2, 3, 4, 5]],  
[[0, 1, 2, 3, 4], [ 5 ]], 
[[0, 1, 2, 3], [ 4, 5 ]], 
[[0, 1, 2], [ 3, 4, 5 ]], 
...
[[0, 1, 2], [ 3, 4 ], [ 5 ]],
...
[[ 0 ], [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ]]
]

Of course this output is only for 6 elements.
If you look at the 2nd, 3rd and 4th line of the output array, it's some sort of combination into 2 sub-arrays.
If you look at the 6th line of the output array, it becomes into 3 sub-arrays.
In the last line every element should be alone in its own sub-array.

I saw the examples on this page and I tried the functions but mine is a little different because the order of the elements need to be respected. This means that regardless of where the brackets are, you should see 1 2 3 4 5 6 on each line.

Also, the functions in the previously mentioned page will give me an array including all the sub-arrays:
[[x,x],[x],[x],[xxx]] I can't use this.

What I need is this format:

[  
[ [ 1 , 2 , 3 ] ] ,  
[ [ 1 , 2 ] , [ 3 ] ] ,  
[ [ 1 ] , [ 2 , 3 ] ] ,  
[ [ 1 ] , [ 2 ] , [ 3 ] ]  
]

I am a beginner, please someone give me a hint on how to do this!

Community
  • 1
  • 1
Horia
  • 15
  • 5
  • what did you try my friend – meda Jun 06 '15 at 03:04
  • What you're looking for is called the [power set](http://en.wikipedia.org/wiki/Power_set), and you may like [this](http://stackoverflow.com/questions/6092781/finding-the-subsets-of-an-array-in-php) :) – someOne Jun 06 '15 at 03:05
  • Just reposting the same question is not how SO works: http://stackoverflow.com/q/30674811/3933332 – Rizier123 Jun 06 '15 at 05:15
  • Hi meda, the elements inside the input array are actually the stops of a route. The input array is the first output permutation of itself. I am looping through permutations. For each perm, I have to get all the powersets so I end up having all the routs possible between all drivers. Once I have all possibilities I will eliminate all duplicates and compare the time of travel between all points. Basically, every sub-array is a possibility and every sub-sub-array is the route assign to a particular driver. – Horia Jun 06 '15 at 16:10
  • Hi someOne, Thanks for referring me to that page. The closest one is the solution given by FallingBullets. However this is not helping me since the function only gives a result array containing 1 level of sub-arrays. Also, it does not respect the order of the elements. I edited my request to be more clear. Please come back and have a look, maybe you can direct me on what to do. You already put me on the right path but I'm not quite there yet. Thanks. – Horia Jun 06 '15 at 16:24

2 Answers2

0

I've just developed a very special way to achieve what you're looking for (traversing a binary tree using binary labels! I don't know if it already exists!!) It's extremely fast and doesn't use recursion :)

<?php
function getSpecialSubsets($in) {
    $in = array_reverse($in);
    $n = count($in);

    $out = array();
    // for every possible route
    for($i = 0; $i<pow(2, $n-1); $i++) {
        $out[$i] = array(array());

        // for every value in the input array
        for($j=$n-1; $j>=0; $j--) {
            $val = $in[$j];
            if(($i >> $j) & 1)
                $out[$i][] = array($val);
            else $out[$i][count($out[$i])-1][] = $val;
        }
    }

    return $out;
}

$subsets = getSpecialSubsets([1, 2, 3, 4]);

// for demonstration purposes only!!
echo "<pre>";
echo preg_replace('~\]\],~', "]],\n", json_encode($subsets));
echo "</pre>";
?>
someOne
  • 1,975
  • 2
  • 14
  • 20
  • For the record: the aforementioned code, yields the special desired subset of the "set of all [partition sets](http://en.wikipedia.org/wiki/Partition_of_a_set)." – someOne Jun 07 '15 at 19:14
  • Thanks a lot someOne, this is exactly what I needed. I made my own function myself by json_encoding and replacing ',' with '],[' but yours is a lot faster. Thanks again!! – Horia Jun 08 '15 at 15:28
  • Hi someOne, my goal was to distribute X points on a map into X routes. At the time where I posted this, I thought that obtaining all permutations of the X points and then running them through getSpecialSubsets will get me all routes possible. Which works. The problem is that I have to get rid of all duplicates which is too long. Running the input array through getSpecialSubsets and then get all permutations of every sub array does not give me all the solutions possible. Is there another way to do this? Also, I need to add another input that limits the max amount of routes. – Horia Jun 08 '15 at 18:05
  • @Horia Hey there! Your new problem is totally a new question and cannot be answer in comments; so, you need to ask a new question. And your welcome :) if this post was useful, then you may accept it as an answer, that's how SO works. – someOne Jun 09 '15 at 03:09
  • Hi, I accepted your answer as a solution for my question and I posted another [here](http://stackoverflow.com/questions/30740821/permutations-of-x-elements-combined-into-1-2-3-4-x-sets-of-sub-sets). This is the question I asked you yesterday. If you have the time, please have a look. Thanks again! – Horia Jun 09 '15 at 19:26
  • Hi, please please please have a look at [my other question](http://stackoverflow.com/questions/30740821/sets-of-combinations-of-subsets-of-unspecified-sizes-including-permutations-of-x) because you are the only who has helped me in here. Just like for this question, it's been flagged as a duplicate and instead of getting to something constructive I'm just arguing on how my question is not a duplicate of another that has nothing to do with it. Please again as you're my only hope. Thanks! – Horia Jun 10 '15 at 23:56
0

This took me hours to be produced!!

You're right, your question is wrongly set as duplicate. However, In that question what you wanted is involved to get all the Partitions of the set instead of what you wanted here (here you wanted a subset of that set.) In either of cases, you can use the following to get the desired output, just replace the name of the desired function in the marked line to whatever you want (I mean you may also change it to getSpecialSubsets() presented above.

As you call tell, the desired principal function of getVerySpecialSubsets() also has the favorable arguments of $level_min and $level_max :)

<?php
function allPermutations($InArray, $InProcessedArray = array())
{
    $ReturnArray = array();
    foreach($InArray as $Key=>$value)
    {
        $CopyArray = $InProcessedArray;
        $CopyArray[$Key] = $value;
        $TempArray = array_diff_key($InArray, $CopyArray);

        if (count($TempArray) == 0)
            $ReturnArray[] = array_values($CopyArray);
        else
            $ReturnArray = array_merge($ReturnArray, allPermutations($TempArray, $CopyArray));
    }
    return $ReturnArray;
}

function powerSet($in,$minLength = 1) { 
   $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) >= $minLength) { 
         $return[] = $out; 
      } 
   } 
   return $return; 
}

function getAllPartitionsOfSet($in) {
    $arr = powerSet(powerSet($in));

    $out = array();
    foreach($arr as $combination) {
        $a = array();
        foreach($combination as $_arr)
            foreach($_arr as $v)
                $a[] = $v;

        // check if $a has duplicates
        // (i.e: the intersection of subsets in $combination is void)
        if(count($a) !== count(array_unique($a)))
            continue;

        // check if there's no difference between $a and $in.
        // (i.e: the union of subsets in $combination is equal to $a)
        if(!empty(array_diff($a, $in)) || !empty(array_diff($in, $a)))
            continue;

        $out[] = $combination;
    }
    return $out;
}

function getVerySpecialSubsets($_in, $level_min = 1, $level_max = 0) {
    $in = array_reverse($_in);
    $n = count($in);

    $level_min = $level_min>0 ? $level_min : 1;
    $level_max = $level_max>0 ? $level_max : $n;

    $allPartitions = getAllPartitionsOfSet($_in); //* marked!
    $out = array();

    foreach($allPartitions as $partition) {
        $levels_count = count($partition);
        if($levels_count>$level_max || $levels_count<$level_min)
            continue;

        // add the permutations of the arrays
        for($i=0; $i<count($partition); $i++) {
            $per = allPermutations($partition[$i]);
            if(count($per)==1)
                continue;

            // combine the permutation with the rest of array
            $first_item = true;
            foreach($per as $_per) {
                $arr = array();
                for($j=0; $j<count($partition); $j++)
                    $arr[] = ($j==$i) ? $_per : $partition[$j];
                $out[] = $arr;
            }
        }
    }

    // last singles
    if($n<=$level_max && $n>=$level_min) {
        $arr_last = array();
        for($k=count($in)-1; $k>=0; $k--)
            $arr_last[] = array($in[$k]);
        $out[] = $arr_last;
    }

    return array_values(array_unique($out, SORT_REGULAR));
}

$subsets = getVerySpecialSubsets([0, 1, 2]);

// for demonstration purposes only!!
echo '<pre>';
echo preg_replace('~\]\],~', "]],\n", json_encode($subsets));
echo '</pre>';
?>
Community
  • 1
  • 1
someOne
  • 1,975
  • 2
  • 14
  • 20
  • Hi, I thank you very very much for doing this for me. This is some amazing php-ing. I'm playing around with your functions and I'm trying to see what each does so I can learn. I have one question without giving you more work. You have done so much for me considering that we don't even know each other. I appreciate it very much. Is there a way to pass $level_min and $level_max into getAllPartitionsOfSet? Maybe I should have explained it in the question but I'm trying to cut into the amount of time. If you chose not to answer, know that I am very grateful for this. Thank you much, sir! – Horia Jun 12 '15 at 03:08
  • Hi. Actually, $level_min and $level_max need to be passed in powerSet as well so I can get just a piece of the final array... – Horia Jun 12 '15 at 04:03
  • @Horia Obtaining the partition of a set, which is a prerequisite of what you want, requires you to have access to _all_ the subset of the powerset, not just a portion of it; but if you have came up with a more efficient solution, you may share it for future visitors, and [your welcome](http://www.parsquran.com/data/show.php?sura=2&ayat=272&user=far&lang=eng&tran=1) :) – someOne Jun 12 '15 at 04:37