BeetleJuice
BeetleJuice

Reputation: 40896

PHP: why do these output different results?

I built two versions of a PHP 7 function that takes an array, and returns a list of arrays showing all the permutations of the original array members. For instance, for input [1,2,3], the expected output would be all six permutations of 1, 2, and 3.

I expected both versions of the function to give the same output but can't figure out why they don't. Here is the first (works as expected):

function permutations(array $input): array {
  $func = function (array $selected, array $chooseFrom, array &$results) 
             use (&$func) {

    foreach ($chooseFrom as $k => $unchosen):
      $selectedCopy = $selected; // make a copy
      $chooseFromCopy = $chooseFrom; // make a copy

      $selectedCopy[] = $unchosen; // add the next unchosen item to selected list
      array_splice($chooseFromCopy, $k,1); // remove the item from chooseFrom list
      $func($selectedCopy, $chooseFromCopy, $results); // recursive call
    endforeach;

    // If we've used all items. Add selection to results
    if (empty($chooseFrom)) $results[] = $selected;
  };

  $results = [];
  $func([], $input, $results);
  return $results;
}

When I call permutations([1,2]) I get the expected result: [[1,2],[2,1]].

Here is the non-working version of the function. The only difference is in the foreach:

function permutations2(array $input): array {

  $func = function (array $selected, array $chooseFrom, array &$results) 
             use (&$func) {

    foreach ($chooseFrom as $k => $unchosen):    
      $chooseFromCopy = $chooseFrom; // make a copy

      $selected[] = $unchosen; // add the next unchosen to the selected list
      array_splice($chooseFromCopy, $k, 1); // remove the item from chooseFrom list
      $func($selected, $chooseFromCopy, $results); // recursive call
    endforeach;

    // If we've used all items. Add selection to results
    if (empty($chooseFrom)) $results[] = $selected;
  };

  $results = [];
  $func([], $input, $results);
  return $results;
}

When I call permutations2([1,2]) I get a bad result: [[1,2],[1,2,1]]

Why is there a difference??

Upvotes: 3

Views: 47

Answers (1)

vijayalakshmi d
vijayalakshmi d

Reputation: 726

The problem is about the variable "$selected" holding the results of the first iteration of the for loop and it needs to be reinitialized before going into the next iteration of the loop. Storing the "$selected" in another variable ( let's say $tempselected) before the for loop and reinitializing "$selected" variable with $tempselected before endforeach statement will make the code work. But this changes is almost same as the working sample of the function :)

<?php

function permutations2(array $input): array {

  $func = function (array $selected, array $chooseFrom, array &$results) 
             use (&$func) {
    $selectedTemp = $selected;

    foreach ($chooseFrom as $k => $unchosen):    
      $chooseFromCopy = $chooseFrom; // make a copy

      $selected[] = $unchosen; // add the next unchosen to the selected list
      array_splice($chooseFromCopy, $k, 1); // remove the item from chooseFrom list
      $func($selected, $chooseFromCopy, $results); // recursive call
      $selected = $selectedTemp;
    endforeach;

    echo("<br>After For Loop <br>");
    // If we've used all items. Add selection to results
      if (empty($chooseFrom))  { $results[] = $selected;  }  
  };

  $results = [];
  $func([], $input, $results);
  return $results;
}
$res = permutations2(['a','b','c']);

Upvotes: 2

Related Questions