JsLearner
JsLearner

Reputation: 466

PHP: Transform string to another string

I would like to Convert simple string to another format based on below logic

Example 1 : if string is 3,4-8-7,5 then I need the set as (3,8,7),(4,8,5). Example 2: If string is "4-5,6-4" then required set will be (4,5,4),(4,6,4).

More Clear Requirements:

if string is 5-6,7,8-2,3-1. It need to be divided first like [5] AND [(6) OR (7) OR (8)] AND [(2) OR (3)] AND [1]. Result must be All possible combination: (5,6,2,1),(5,6,3,1),(5,7,2,1),(5,7,3,1),(5,8,2,1),(5,8,3,1).

The Logic behind to building the set are we need to consider ',' as OR condition and '-' as AND condition.

I am trying my best using For loop but unable to find solution

$intermediate = array();

$arry_A = explode('-', '3,4-8-7,5');

for ($i = 0; $i < count($arry_A); $i++) {

$arry_B = explode(',', $arry_A[$i]);

for ($j = 0; $j < count($arry_B); $j++) {  

    if (count($intermediate) > 0) {

        for ($k = 0; $k < count($intermediate); $k++) { 

            $intermediate[$k] = $intermediate[$k] . ',' . $arry_B[$j];

        }

    } elseif (count($intermediate) === 0) {

        $intermediate[0] = $arry_B[$j];

    }        

}
}

echo $intermediate, should give final result.

Upvotes: 2

Views: 190

Answers (1)

Marc
Marc

Reputation: 3709

Cool little exercise!

I would do it with the following code, which I will split up for readability:

I used an array as output, since it's easier to check than a string.

First, we initialize the $string and create the output array $solutions. We will calculate the maximum of possible combinations from the beginning ($results) and fill the $solutions array with empty arrays which will be filled later with the actual combinations.

$string = '3,4-8-7,5';
$solutions = array();
$results = substr_count($string,',')*2;
for($i = 0; $i < $results; $i++) {
  array_push($solutions,array());
}

We will need two helper functions: checkSolutions which makes sure, that the combination does not yet exist more than $limit times. And numberOfORAfterwards which will calculate the position of an OR pattern in the $string so we can calculate how often a combination is allowed in the single steps of the walkthrough.

function checkSolutions($array,$solutions,$limit) {
  $count = 0;
  foreach($solutions as $solution) {
    if($solution === $array) $count++;
  }
  if($count < $limit) return true;
  else return false;
}

function numberOfORAfterwards($part,$parts) {
  foreach($parts as $currPart) {
    if($currPart === $part) $count = 0;
    if(isset($count)) if(!ctype_digit($currPart)) $count++;
  }
  return $count;
}

Now the main part: We are going to loop over the "parts" of the $string a part are the digits between AND operations.

If you need further explanation on this loop, just leave a comment.

$length = 0;
// split by all AND operations
$parts = explode('-',$string);
foreach($parts as $part) {
  if(ctype_digit($part)) {
    // case AND x AND
    foreach($solutions as &$solution) {
      array_push($solution,$part);
    }
  } else {
    // case x OR x ...
    $digits = explode(',',$part);
    foreach($digits as $digit) {
      for($i = 0; $i < $results/count($digits); $i++) {
        foreach($solutions as &$solution) {
          if(count($solution) == $length) {
            $test = $solution;
            array_push($test,$digit);
            $limit = numberOfORAfterwards($part,$parts);
            echo $digit.' '.$limit.'<br>';
            if(checkSolutions($test,$solutions,$limit)) {
              array_push($solution,$digit);
              break;
            }
          }
        }
      }
    }
  }
  $length++;
}

print_r($solutions);

Some tests:

String: 3,4-8-7,5
Combinations: (3,8,7)(3,8,5)(4,8,7)(4,8,7)

String: 5-6,7,8-2,3-1
Combinations: (5,6,2,1)(5,6,3,1)(5,7,2,1)(5,7,3,1)(5,8,2,1)(5,8,2,1)

String: 2,1-4-3,2-7,8-9
Combinations: (2,4,3,7,9)(2,4,3,8,9)(2,4,2,7,9)(1,4,3,7,9)(1,4,2,8,9)(1,4,2,8,9)

String: 1,5-3,2-1
Combinations: (1,3,1)(1,2,1)(5,3,1)(5,3,1)

Upvotes: 1

Related Questions