Simple facebook test assignment is not so simple in fact

Given Problem

Input string: 33221 Output string: 322211

So you have to outup number + its repetitions in a row

Possible Solutions

First try, it took me 5 min and 2 iterations to make it working:

$last = '';
$last_count = '';

$string = "4441";

foreach (str_split($string) as $index => $letter) {
  if($last != $letter){
    echo $last.($last_count);
    $last = $letter;
    $last_count = 1;
  }else{
    $last_count += 1;
  }

  if($index == strlen($string) - 1){
    echo $last.($last_count);
  }
}

This code has 2 main drawbacks:

  • On first iteration it prints empty string (it is right but poor solution)
  • It has 2 identical lines of code (line 8 and 16)

Spending 2 more minutes I did this:

$last = '';
$last_count = 1;

$string = "33221";

if(strlen($string)){
  foreach (str_split($string) as $index => $letter) {
    if($index === 0){
      $last = $letter;
    }elseif($last != $letter){
      echo $last.($last_count)."\n";
      $last = $letter;
      $last_count = 1;
    }else{
      $last_count += 1;
    }
  }
  echo $last.($last_count)."\n";
}

Here again we have the same line repeating, but now it is outside the loop.

Trying to do it in a more functional way:

error_reporting(E_ALL ^ E_STRICT);

$string = "33221";

$data = (object)array('last' => '', 'count' => 0);
array_walk(str_split($string), function($letter, $index, $temp){
  if($letter == $temp->last){
    $temp->count += 1;
  }else{
    if($temp->last) echo $temp->last.$temp->count;
    $temp->last = $letter;
    $temp->count = 1;
  }
}, $data);
if($data->last) echo $data->last.$data->count;

And one more way using static variables inside a function:

error_reporting(E_ALL ^ E_STRICT);

$string = "33221";

function checkPairs($letter = null) {
  static $count = 0;
  static $last = null;

  if($last == $letter){
    $count++;
  }elseif($last){
    echo $last.$count+1;
    $count = 0;
  }
  $last = $letter;
}

array_walk(str_split($string), function($letter, $index){
  checkPairs($letter);
});
checkPairs();

Here is a solution which will work only for unique groups:

$string = "33221";

$array = str_split($string);
$stack = array();
while($letter = array_shift($array)){
  if(isset($stack[$letter])){
    $stack[$letter] += 1;
  }else{
    $stack[$letter] = 1;
  }
}

foreach($stack as $letter => $count){
  echo $letter.$count;
}