2010-04-02 10 views
7

ich sehr lange Integer-Sequenzen haben, die wie folgt aussehen (beliebiger Länge!):Encode/komprimieren Folge von sich wiederholenden Zahlen

0000000001110002220033333 

Jetzt brauche ich einige Algorithmus diese Zeichenfolge in so etwas wie

komprimiert zu konvertieren
a9b3a3c3a2d5 

Das bedeutet "a 9 mal, dann b 3 mal, dann 3 mal" und so weiter, wobei "a" für 0 steht, "b" für 1, "c" für 2 und "d" für 3.

Wie würden Sie das tun? Bisher kam mir nichts passendes in den Sinn, und ich hatte kein Glück mit Google, weil ich nicht wirklich wusste, wonach ich suchen sollte. Wie heißt diese Art der Kodierung/Komprimierung?

PS: Ich werde die Codierung mit PHP, und die Dekodierung in JavaScript zu tun.

Bearbeiten: Vielen Dank!

endete ich mit dieser Funktion für die Codierung bis:

protected function numStringToRle($s){   
     $rle = ''; 
     $count = 1; 
     $len = strlen($s); 
     for($i = 0; $i < $len; $i++){ 
      if($i != $len && isset($s[$i+1]) && $s[$i] == $s[$i+1]){ 
       $count++;     
      } else { 
       $rle .= chr($s[$i] + 97).($count == 1 ? '' : $count);         
       $count = 1; 
      } 
     } 
     return $rle;    
} 

Und das für die Decodierung:

var decodeCoords = function(str) { 

    str = str.replace(/(.)(\d+)/g, function(_, x, n) { 
     return new Array(parseInt(n, 10) + 1).join(x); 
    }); 

    return str. 
    replace(/a/g, '0'). 
    replace(/b/g, '1'). 
    replace(/c/g, '2'). 
    replace(/d/g, '3');  
}; 
+1

Was genau Sie diese mit für? Sind Sie sicher, dass Sie es nicht einfach mit Gzip komprimieren können? http: // Stapelüberlauf.com/questions/294297/javascript-implementation-of-gzip Es wird zeitlich und räumlich effizienter sein, und es ist bereits für Sie getan. – ryeguy

+0

gzip ist keine Option, weil ich es mit Javascript dekodieren muss. Ich verwende es als eine Art Bitmaske für ein 2D-Spiel. – Alex

Antwort

7

Es Run Length Encoding

Basisgeber in PHP aufgerufen:

function numStringToRle($s){ 
    $rle = ''; 
    $count = 1; 
    $len = strlen($s); 
    for ($i = 0; $i < $len; $i++){ 
     if ($i != $len && $s[$i] == $s[$i+1]){ 
      $count++;     
     }else{ 
      $rle .= chr($s[$i] + 97).$count;  
      $count = 1; 
     } 
    } 
    return $rle; 
} 

gewarnt es schlecht Probleme mit einem String wie

123456789123456789 

Vorform Wenn Sie eine Zeichenfolge werden würden Handhabung, die eine Menge einzelner einzelne Zeichen haben, können Sie besser wäre, eine gewisse Komplexität und nicht schreiben die Länge hinzufügen des Laufs, wenn die Länge des Laufs 1 ist.

//change 
$rle .= chr($s[$i] + 97).$count;  

//to 
$rle .= chr($s[$i] + 97).($count == 1 ? '' : $count); 

//or 
$rle .= chr($s[$i] + 97) 
if ($count != 1){ 
    $rle .= $count; 
} 
+0

Funktioniert wie ein Charme, thx! – Alex

+0

Ich suchte nach dem Namen dieses Algorithmus. Vielen Dank! – Jack

2

Hier ist eine naive Implementierung von was Sie wollen.

$toEncode = '0000000001110002220033333'; 
$currentChar = '-1'; 
$length = strlen($toEncode); 
$encoded = ''; 
$currentNbrChar = 0; 
for($i = 0; $i < $length; $i++){ 
    if($toEncode[$i] != $currentChar){ 
    if($currentChar != '-1'){ 
     $encoded .= chr(97 + $currentChar).$currentNbrChar; 
    } 
    $currentNbrChar = 0; 
    $currentChar = $toEncode[$i]; 
    } 
    $currentNbrChar ++; 
} 
if($currentChar != '-1'){ 
    $encoded .= chr(97 + $currentChar).$currentNbrChar; 
} 
echo $encoded; 
+0

Danke! Das funktioniert perfekt. – Alex

2

Hier ist eine kürzere Version:

function smush(str) { 
    return str.replace(/((.)\2*)/g, function(_, w, x) { 
    return x + w.length; 
    }); 
} 

bearbeiten oh ich sehe man mit PHP kodieren möchten; Entschuldigung, ich weiß das nicht. Hier ist ein Decoder in einem ähnlichen Geist:

function unsmush(str) { 
    return str.replace(/(.)(\d+)/g, function(_, x, n) { 
    return new Array(parseInt(n, 10) + 1).join(x); 
    }); 
} 
0

Gerade FYI, könnten Sie wahrscheinlich Ihre Daten gzip und das Durchsuchen wird automatisch entpacken. Für die meisten Implementierungen wird dies besser funktionieren als RLE. Aber offensichtlich weniger Spaß.

0
$str="0000000001110002220033333"; 

//$c will count the number of occurances. 

$c=1; 

$lastInt=substr($str,0,1); 

$str=substr($str,1); 

$resultStr=''; 

$loopEnd=strlen($str); 


for($i=1; $i<=$loopEnd+1;$i++) 

{ 

    $nowInt=substr($str,0,1); 
    if($lastInt==$nowInt) 
    { 
     $c++; 
     $str=substr($str,1); 
    } 
    else 
    { 
     $char=chr((int)$lastInt + 97); 
     $resultStr=$resultStr.$char.$c; 
     $str=substr($str,1); 
     $c=1; 
     $lastInt=$nowInt; 
    } 
} 

// we use if condition since for loop will not take the last integer if it repeats. 

if($c>1) 
{ 

$char=chr((int)$lastInt + 97); 

$resultStr=$resultStr.$char.$c; 

} 

echo $resultStr; 
0
function compress($str) { 
$strArr = str_split($str.'0'); 
$count = 0; 
$resStr = ''; 
$strCheck = $strArr[0]; 
foreach($strArr as $key => $value) 
{ 
    if($strCheck == $value) 
    { 
     $count++; 
    } 
    else 
    { 
     if($count == 1) 
     { 
      $strCheck = $value; 
      $resStr .= $strArr[$key-1]; 
      $count=1; 
     } 
     elseif($count == 2) 
     { 
      $strCheck = $value; 
      $resStr .= $strArr[$key-1].$strArr[$key-1]; 
      $count=1; 
     } 
     else 
     { 
      $strCheck = $value; 
      $resStr .= $strArr[$key-1].$count; 
      $count=1; 
     } 
    } 

} 
return $resStr; 

}

Verwandte Themen