: : g_POLE

Balíček obsahuje funkce pro kompresi rozměrných polí do DB. Je zaměřen především na textová pole než binární. U binárních jen ukazuji kompresi, dekompresi si dopište.

Použití:
Je výhodné po postupně rozšiřující se množinu údajů uchovanou v poli (i více rozměrném), pro údaje kde převládá základní množina a nebo pro binání pole.
Např. na ukládání piškvorek.

000
010
011
  Pro uložení malého binárního 2D pole do DB můžem využít několik cest:
a) uložit jako řetězec 000010011, který nám zabere 9b (čisté hodnoty) ArrayToString
b) jako řetězec znaků 478, který zabere jen 3b (souřadnice nenulových hodnot) binAr2DToString
c) jako řetězec znaků , tj. v hexu (0980), který zabere 2b. (binární hodnota z a) převedna na string) bin2str(ArrayToString($pole));

000000
000000
000000
000010
000111
011010
  Pro uložení středního (tj. do 256 políček) binárního 2D pole do DB můžem opět využít známé cesty:
a) uložit jako řetězec 000000000000000000000010000111011010, který nám zabere 36b (čisté hodnoty) ArrayToString
b) jako řetězec znaků  ", tj. v hexu (161b1c1d1f2022), který zabere jen 7b (souřadnice nenulových hodnot) binAr2DToString
c) jako řetězec znaků  , tj. v hexu (0000021da0), který zabere 5b. (binární hodnota z a) převedna na string) bin2str(ArrayToString($pole))

000000
000000
000000
000010
000212
023010
  Pro uložení mixovaného 2D pole do DB nabízím nové metody, protože body b) a c) nejdou snadno použít:
a) uložit jako řetězec 000000000000000000000010000212023010, který opět zabere 36b (čisté hodnoty) ArrayToString

d) jako řetězec znaků DDE…, tj. v hexu (0304440304044405450185020504), který opět zabere jen 14b. (rozmer je limitovan poctem pouzitych znaku) StrAr2DToString

Pole 30x30, 4 možné stavy jiné než 0, složen zpět do řetězce přes funkci StringBackTo2DStrAr:
<?
  $pis_ar = RozdelSkoky(array("0"=>array("X","O","x","o")),4); 
  $strulozen = StrAr2DToString($obrpole,4,$pis_ar,chr(3)); 
  echo "Uložen jako: ".$strulozen." s délkou ".strlen($strulozen)."b (hodnot*2)<br/>"; 
  echo "<small>".nl2br(Zobraz2DArray(StringBackTo2DStrAr($strulozen,$pis_ar,30,30,chr(3))))."</small>"; 
?>
Uložen jako: L N NO Ź  s délkou 16b (hodnot*2)












O
X
OXO
OxX















Kód lze nadále upravovat. Při častém používání lze tabulky napsat do kódu napevno, binární převody generovat - či jinak zjednodušovat a zrychlovat. Důležitou výhodou je ušetření místa. V posledním případě má uložené pole teméř 1kb, kdežto v šetřivém zápisu toho dosáhneme až ve 450 kole hry.

Kód:
g_pole.php
<? /* POLE */
$g_pole_true = true;

  function CountBinStr($bins) {
    $retnum = 0;
    $bins = substr($bins.'00000000',0,8);
    // 128,64,32,16,8,4,2,1

    $r = 128;
    for ($i=0;$i<8;$i++) {
      if ($bins{$i}!=0) $retnum += $r;
      $r = $r/2;
    }
    return $retnum;
  }

  function bin2str($binstr) {
  
    $ret = '';
    $mez = '';
    for ($i=0;$i<strlen($binstr);$i++) {
      if (strlen($mez)==8) {
        $ret .= chr(CountBinStr($mez));
        $mez = '';
      }
      $mez .= $binstr{$i};
    }
    if (strlen($mez)>0) $ret .= chr(CountBinStr($mez));
    return $ret;
    
  }
  
  function ArrayToString($ar) {
    $ret = '';
    for ($i=0; $i<count($ar); $i++) {
      if (is_array($ar[$i])) $ret .= Implode('',$ar[$i]);
      else $ret .= $ar[$i];
    }
    return $ret;
  }
  
  function BinAr2DToString($ar) {
    $ret = '';
    if (count($ar)<1 || !is_array($ar[0])) return $ret;
    $sirka = count($ar[0]);
    $vyska = count($ar);
    $rozmer = $vyska*$sirka;
    if ($rozmer<=10) {  // 3*3, 2*5

      for ($y=0; $y<$vyska; $y++) 
        for ($x=0; $x<$sirka; $x++) {
          if ($ar[$y][$x]!=0) $ret .= ($y*$sirka)+$x;
        }
      return $ret;
    } else
    if ($rozmer<=256) { // do 16x16

      for ($y=0; $y<$vyska; $y++) 
        for ($x=0; $x<$sirka; $x++) {
          if ($ar[$y][$x]!=0) $ret .= chr(($y*$sirka)+$x);
        }
      return $ret;
    } else 
    if ($rozmer<=65536) { // do 255x255

      for ($y=0; $y<$vyska; $y++) 
        for ($x=0; $x<$sirka; $x++) {
          if ($ar[$y][$x]!=0) $ret .= chr($y).chr($x);
        }
      return $ret;
    } // else... atd.

  }

  function RozdelSkoky($ar,$druhu) {
    $skok = ceil(256 / $druhu);
    $retar = array();
    for ($y=0; $y<count($ar); $y++) 
      for ($x=0; $x<count($ar[0]); $x++) {
        $ch = $ar[$y][$x];
        if ($ar[$y][$x]!='0' && !isset($retar[$ch])) $retar[$ch] = count($retar)*$skok;
        if (count($retar)==$druhu) break;  
      }
    return $retar;
  }
  
  $muj_ar = RozdelSkoky(array('0'=>array('1','2','3','4')),4);
  $pis_ar = RozdelSkoky(array('0'=>array('X','O','x','o')),4);
  function StrAr2DToString($ar,$druhu=1,$ar_skoku=0,$def='0') {
    $ret = '';
    if (count($ar)<1 || !is_array($ar[0])) return $ret;
    $sirka = count($ar[0]);
    $vyska = count($ar);
    $rozmer = $vyska*$sirka;
    if (empty($ar_skoku) || !is_array($ar_skoku)) 
      $ar_skoku = RozdelSkoky($ar,$druhu);
    else
      $druhu = count($ar_skoku);
    if ($rozmer<=65536) { // do 255x255

      for ($y=0; $y<$vyska; $y++) 
        for ($x=0; $x<$sirka; $x++) {
          $ch = $ar[$y][$x];
          if ($ch!=$def) $ret .= chr($ar_skoku[$ch]+$y).chr($x);
        }
      return $ret;
    } // else... atd.

  }
  
  function KlicDleMeziHodnoty($ar,$hod) {
    $ret = '0';
    if (count($ar)>0) {
      $l=0;
      asort($ar);
      while(list($k,$h)=each($ar)) {
        if ($hod>=$l && $hod<=$h) return $k;
        $l=$h;        
      }
    }
    return $ret;
  }
  
  function CreateEmptyAr($hei,$wid,$def='0') {
    $retar = array();
    for ($y=0; $y<$hei; $y++) {
      $retar[$y] = array();
      for ($x=0; $x<$wid; $x++) {
        $retar[$y][$x]=$def;
      }
    }
    return $retar;
  }

  function StringBackTo2DStrAr($str,$ar_skoku,$hei,$wid,$def='0') {
    $retar = CreateEmptyAr($hei,$wid,$def);
    $skok = ceil(255/count($ar_skoku));
    $rozmer = $hei*$wid;
    $delka = strlen($str);
    if ($delka % 2 != 0) return $retar;

    for ($i=0;$i<$delka;$i++) {
      $yord = ord($str{$i});
      $i++;
      $x = ord($str{$i});
      $y = $yord % $skok;
      $h = KlicDleMeziHodnoty($ar_skoku,$yord - ($yord % $skok));
      $retar[$y][$x] = $h;

    }

    return $retar;
  }
  
  function Zobraz2DArray($ar) {
    $ret = '';
    if (count($ar)<1 || !is_array($ar[0])) return $ret;
    $sirka = count($ar[0]);
    $vyska = count($ar);
    for ($y=0; $y<$vyska; $y++) {
      for ($x=0; $x<$sirka; $x++) {
        $ret .= $ar[$y][$x];
      }    
      $ret .= "\n";
    }
    return $ret;
  }

  function ZobrazArray($ar) {
    reset($ar);
    while(list($k,$h)=each($ar)) {
      echo $k.','.$h.'|'."\n";
    }
  }

?>