HTML

Programozó Páternoszter

Ez a Programozó Páternoszter (PP) blogja, a programozásról szól. Aktualitása, hogy a Debreceni Egyetem Informatikai Kara Magasszintű programozási nyelvek 1-2, C++ esattanulmányok, Java esettanulmányok című kurzusainak blogja is egyben.

A vadászat

A Debreceni Egyetem Programozói Évkönyve: az UDPROG projekt. A szakmai fórumunk a Facebook-en. Az új előadások a prezin.
A régi előadások:
Prog1:
1. C bevezetés
2. C tárgyalás
3. C befejezés
4. C a gyakorlatban
5. C++ bevezetés
6. C++ tárgyalás
7. C++ befejezés
8. C++ a gyakorlatban
9. Java platform bevezetés
10. Kvantuminformatikai alg. bev.
Prog2:
1. Java bevezetés
2. Java tárgyalás
3. Java befejezés
4. Java a gyakorlatban
5. Software Engineering bev.
6. Java EE bevezetés
7. AspectJ bevezetés
8. BPMN-BPEL SOA programozás
9. C++ haladó
10. Tensorflow

Kövess engem!

Friss topikok

Linkblog

Gyönyör a tömör

2011.02.19. 12:00 nb

man compress:

DESCRIPTION
       The  compress  utility  shall attempt to reduce the size of the named files by using adaptive Lempel-Ziv coding algorithm.

       Note:  Lempel-Ziv is US Patent 4464650, issued to William Eastman, Abraham Lempel, Jacob Ziv, Martin Cohn on August 7th, 1984, and assigned to Sperry Corporation.

       Lempel-Ziv-Welch  compression  is  covered  by US Patent 4558302, issued to Terry A. Welch on December 10th, 1985, and assigned to Sperry Corporation."
de már jópár éve lejárt a szabadalmi oltalom, egyik eredmény: a gif visszaszorult, a png elterjedt. (A Lempel-Ziv-Welch algoritmust használja a gif formátuma, sok tömörítő, például a compress, gzip, zip.)
Az algoritmus remek leírását találjuk a Rónyai-Iványos-Szabó Algoritmusok könyvben. Alább egy naivabb  implementációt adunk a Tusnády: Sztochasztikus számítástechnika című könyv alapján: jön a 0-1 sorozat, betűnként olvassuk, ha olyan rész jön, ami még "nincs a zsákban", akkor "letörjük és be a zsákba":

00011101110 -> 0 00 1 11 01 110

 a tördelést egy bináris fával könnyen meg tudjuk valósítani:

                 / 
       0             1
   0      1              1
                       0

Így használd:

[norbi@sgu C]$ more b.txt
00011101110
[norbi@sgu C]$ gcc z.c -o z -std=c99
[norbi@sgu C]$ ./z < b.txt
00011101110
---------1
------------0
------1
---/
---------1
------0
---------0

 A kód, a harmadik labor billenytűzős feladata lesz, de immár nem csak képpel:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

typedef struct binfa
{
  int ertek;
  struct binfa *bal_nulla;
  struct binfa *jobb_egy;

} BINFA, *BINFA_PTR;

BINFA_PTR
uj_elem ()
{
  BINFA_PTR p;

  if ((p = (BINFA_PTR) malloc (sizeof (BINFA))) == NULL)
    {
      perror ("memoria");
      exit (EXIT_FAILURE);
    }
  return p;
}

extern void kiir (BINFA_PTR elem);
extern void szabadit (BINFA_PTR elem);

int
main (int argc, char **argv)
{
  char b;

  BINFA_PTR gyoker = uj_elem ();
  gyoker->ertek = '/';
  BINFA_PTR fa = gyoker;

  while (read (0, (void *) &b, 1))
    {
      write (1, &b, 1);
      if (b == '0')
	{
	  if (fa->bal_nulla == NULL)
	    {
	      fa->bal_nulla = uj_elem ();
	      fa->bal_nulla->ertek = 0;
	      fa->bal_nulla->bal_nulla = fa->bal_nulla->jobb_egy = NULL;
	      fa = gyoker;
	    }
	  else
	    {
	      fa = fa->bal_nulla;
	    }
	}
      else
	{
	  if (fa->jobb_egy == NULL)
	    {
	      fa->jobb_egy = uj_elem ();
	      fa->jobb_egy->ertek = 1;
	      fa->jobb_egy->bal_nulla = fa->jobb_egy->jobb_egy = NULL;
	      fa = gyoker;
	    }
	  else
	    {
	      fa = fa->jobb_egy;
	    }
	}
    }

  printf ("\n");
  kiir (gyoker);
  extern int max_melyseg;
  printf ("melyseg=%d", max_melyseg);
  szabadit (gyoker);
}

static int melyseg = 0;
int max_melyseg = 0;

void
kiir (BINFA_PTR elem)
{
  if (elem != NULL)
    {
      ++melyseg;
      if (melyseg > max_melyseg)
	max_melyseg = melyseg;
      kiir (elem->jobb_egy);
      for (int i = 0; i < melyseg; ++i)
	printf ("---");
      printf ("%c(%d)\n", elem->ertek < 2 ? '0' + elem->ertek : elem->ertek,
	      melyseg);
      kiir (elem->bal_nulla);
      --melyseg;
    }
}

void
szabadit (BINFA_PTR elem)
{
  if (elem != NULL)
    {
      szabadit (elem->jobb_egy);
      szabadit (elem->bal_nulla);
      free (elem);
    }
}

3 kisbajnokság

Annak, aki először megmondja, hogy a esr.fsf.hu/hacker-howto.html lap bitenként nézve milyen mély ilyen "Ziv-Lempel" fát épít fel. Tipp: írj egy dump progit, ami 0-1 karakterekben kiköpi a bináris bemenetét és tedd ezt:

[norbi@sgu C]$ wget http://esr.fsf.hu/hacker-howto.html
[norbi@sgu C]$ cat hacker-howto.html|./d >hacker-howto.html.01
[norbi@sgu C]$ more hacker-howto.html.01
ezt már megeszi a fenti kód, csak ki kell íratnod a mélységet. (Ne feledd: a laborteljesítés feladata olyasmi lesz, hogy binárisan kell majd feldolgoznod a bemenetet, pontos specifikáció majd később.)

A program a 4. laboron kerül terítékre, de már a harmadikon szerepel majd az említett dump:

 Előrehivatkozok itt most a Labormérés otthon, avagy hogyan dolgozok fel egy pédát c. posztra, aminek Móricka rajza segít a "mélység" értelmezésében.

A laborok teljesítésének egyik szükséges feltétele

Idézet az 1. előadásból:

Labor teljesítésének további szükséges feltétele egy saját program
bemutatása a laborközösség előtt, a félév közepén. A feladat kötött:
adok egy karakterekre (0,1 betűkre) működő algoritmust, azt kell
átírni, hogy bináris bemenetre (0, 1 bitekre) működjön (lásd 3 előadás
és labor). A félév végén pedig egy saját robofocis fejlesztés
bemutatása..

S ugye annyit nehezítettünk, hogy idén már a C++ változatot kell védeni (de éppen e miatt ettől még elválaszt minket pár előadás). A karakterekre működő LZW fa építő most szerepelt, de binárisra úgy engedtük rá, hogy azt először az iménti dump progival karakteres 0,1 állománnyá alakítottuk. Most olyat kell írnod, ami kapásból binárisat dolgoz fel! Íme a specifikáció:

Állomány: BNbeadando.c (saját monogram, ékezetes betű nincs)
Parancssor:  ./BNbeadando input_fájl_neve -o kimeneti_fájl_neve (ha nem így indítják, kiírja, hogy így kellene használni és leáll)
Kimenet: tartalmazza a 0,1 bináris LZW fát, majd a fa mélységét, végül a fa ághosszainak szórását (utóbbi a negyedik laboron is téma)

(Lesz néhány teszt állomány megadva, ahol előre meg lehet nézni, hogy megfelelően működik-e a kifejlesztett progitok. Aki előre dolgozna: z.c, illetve a humán genom 2. kromoszómája mindig kéznél van: hs_...chr2.fa.gz a posztban használt fájlnév változott, dolgozz majd ezzel: ftp://ftp.ncbi.nlm.nih.gov/genomes/H_sapiens/CHR_02/hs_alt_HuRef_chr2.fa.gz aki kiszámolja itt elsőként az LZW fa mélységét, annak 3 trófea, ha a d.c-t módosítja, hogy az az első "sort" kidobja, további 1, s az így kapott mélységre további 1.)

 

16 komment

Címkék: tömörítés gif rekurzió zip welch struct lzw ziv lempel önhivatkozó struktúrák

A bejegyzés trackback címe:

https://progpater.blog.hu/api/trackback/id/tr452661235

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

nb · http://fersml.blog.hu 2011.02.22. 19:40:02

Bugos a kód, megtalálod?

Joe89 2011.02.24. 22:36:29

Nekem 259-et írt ki mélységnek... Ez jó?? Vagy legalább közel van??? ... :P ... Egyébként melyik kód bugos, a dump, vagy a láncolt lista(fa)???

Painkiller19910110 2011.02.25. 17:50:23

A fa mélysége: 34310 szerintem.

nb · http://fersml.blog.hu 2011.02.25. 19:09:22

@Joe89: magam a fa kódjában lévőt látom, de lehet, hogy a másikban is van :(

Szerintem a 259 sok... hogy jött ki? Nekem a hacker howto doksi 0,1 karakteres dumpja 274480 bájt, Neked? (a fenti hacker-howto.html.01 állomány)

nb · http://fersml.blog.hu 2011.02.25. 19:10:08

@Painkiller19910110: ez már csillagászatinak mondható, ha a 259 nagy volt :) Hogy jött ki?

nb · http://fersml.blog.hu 2011.02.26. 13:06:11

@kovdog: nagyon közel vagy..., de nekem mást nyomtat ki... hogy jött ki Neked? (Mert a kicsi különbség már a mélység értelmezéséből is adódhat)

Magam így értelemezem:

00011101110
---------1(3)
------------0(4)
------1(2)
---/(1)
---------1(3)
------0(2)
---------0(3)
melyseg=4

nb · http://fersml.blog.hu 2011.02.27. 10:58:39

@Painkiller19910110: gratulálok, ott a trófea!

-----------------------------------------------------------------------------------1(28)
--------------------------------------------------------------------------------1(27)
-----------------------------------------------------------------------------------------1(30)
--------------------------------------------------------------------------------------1(29)
-----------------------------------------------------------------------------------0(28)
-----------------------------------------------------------------------------------------1(30)
-----------------------------------------------------------------------------------------------1(32)
--------------------------------------------------------------------------------------------0(31)
--------------------------------------------------------------------------------------0(29)
-----------------------------------------------------------------------------------------0(30)
--------------------------------------------------------------------------------------------0(31)

Joe89 2011.02.27. 11:23:41

Áhhh, erről lekéstem, pedig nekem is kijött a 32 ... :P ... Majd legközelebb ... :D

nb · http://fersml.blog.hu 2011.02.27. 11:42:01

@nb: az új csomópontok két mutatója nem volt NULLázva, pl. most már: fa->bal_nulla->bal_nulla = fa->bal_nulla->jobb_egy = NULL;

nb · http://fersml.blog.hu 2011.02.27. 11:43:07

@Joe89: az aktuálisan szereplő kódban benne hagytam a mélységel kapcsolatos dolgokat, magam így írattam ki.

pi_zoli 2011.04.19. 12:25:01

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <math.h>

#include <string.h>

typedef struct binfa

{

int ertek;

struct binfa *bal_nulla;

struct binfa *jobb_egy;

} BINFA, *BINFA_PTR;

BINFA_PTR

uj_elem ()

{

BINFA_PTR p;

if ((p = (BINFA_PTR) malloc (sizeof (BINFA))) == NULL)

{

perror ("memoria");

exit (EXIT_FAILURE);

}

return p;

}

extern void kiir (BINFA_PTR elem,FILE *c);

extern void ratlag (BINFA_PTR elem);

extern void rszoras (BINFA_PTR elem);

extern void szabadit (BINFA_PTR elem);

int

main (int argc, char **argv)

{

char b;

int a,i;

FILE *f,*c;

f=fopen(argv[1],"r");

c=fopen(argv[3],"w");

BINFA_PTR gyoker = uj_elem ();

gyoker->ertek = '/';

BINFA_PTR fa = gyoker;

if(!strncmp(argv[2],"-o",2) && argc==4)

{while ((b=getc(f))!=EOF)

{

for (i = 0; i < 8; i++)

{

a = b & 0x80;

if ((a >> 7) == 0)

{

if (fa->bal_nulla == NULL)

{

fa->bal_nulla = uj_elem ();

fa->bal_nulla->ertek = 0;

fa = gyoker;

}

else

{

fa = fa->bal_nulla;

}

}

else

{

if (fa->jobb_egy == NULL)

{

fa->jobb_egy = uj_elem ();

fa->jobb_egy->ertek = 1;

fa = gyoker;

}

else

{

fa = fa->jobb_egy;

}

}

b <<= 1;

}

}

}else printf("./programnev bemeneti_file -o kimeneti_file ");

// fprintf (c,"\n");

kiir (gyoker,c);

extern int max_melyseg, atlagosszeg, melyseg, atlagdb;

extern double szorasosszeg, atlag;

fprintf (c,"melyseg=%d\n", max_melyseg);

/* Átlagos ághossz kiszámítása */

atlagosszeg = 0;

melyseg = 0;

atlagdb = 0;

ratlag (gyoker);

atlag = atlagosszeg / atlagdb;

/* Ághosszak szórásának kiszámítása */

atlagosszeg = 0;

melyseg = 0;

atlagdb = 0;

szorasosszeg = 0.0;

rszoras (gyoker);

double szoras = 0.0;

if (atlagdb - 1 > 0)

szoras = sqrt( szorasosszeg / (atlagdb - 1));

else

szoras = sqrt (szorasosszeg);

fprintf (c,"altal=%f\nszoras=%f\n", atlag, szoras);

szabadit (gyoker);

fclose(f);

fclose(c);

}

// a Javacska ONE projekt Hetedik Szem/TudatSzamitas.java mintajara

// sourceforge.net/projects/javacska/

// az atlag() hivasakor is inicializalni kell oket, a

// a rekurziv bejaras hasznalja

int atlagosszeg = 0, melyseg = 0, atlagdb = 0;

void

ratlag (BINFA_PTR fa)

{

if (fa != NULL)

{

++melyseg;

ratlag (fa->jobb_egy);

ratlag (fa->bal_nulla);

--melyseg;

if (fa->jobb_egy == NULL && fa->bal_nulla == NULL)

{

++atlagdb;

atlagosszeg += melyseg;

}

}

}

// a Javacska ONE projekt Hetedik Szem/TudatSzamitas.java mintajara

// sourceforge.net/projects/javacska/

// az atlag() hivasakor is inicializalni kell oket, a

// a rekurziv bejaras hasznalja

double szorasosszeg = 0.0, atlag = 0.0;

void

rszoras (BINFA_PTR fa)

{

if (fa != NULL)

{

++melyseg;

rszoras (fa->jobb_egy);

rszoras (fa->bal_nulla);

--melyseg;

if (fa->jobb_egy == NULL && fa->bal_nulla == NULL)

{

++atlagdb;

szorasosszeg += ((melyseg - atlag) * (melyseg - atlag));

}

}

}

//static int melyseg = 0;

int max_melyseg = 0;

void

kiir (BINFA_PTR elem,FILE *c)

{

if (elem != NULL)

{

++melyseg;

if (melyseg > max_melyseg)

max_melyseg = melyseg;

kiir (elem->jobb_egy,c);

for (int i = 0; i < melyseg; ++i)

fprintf (c,"---");

fprintf (c,"%c(%d)\n", elem->ertek < 2 ? '0' + elem->ertek : elem->ertek,

melyseg);

kiir (elem->bal_nulla,c);

--melyseg;

}

}

void

szabadit (BINFA_PTR elem)

{

if (elem != NULL)

{

szabadit (elem->jobb_egy);

szabadit (elem->bal_nulla);

free (elem);

}

}

nb · http://fersml.blog.hu 2011.04.19. 13:49:25

@pi_zoli: sikeres volt a védés, de a kommentet olvasük ne feledjék, hogy a bemenő paraméterek kezelése problémás volt (a hallgató ezt a C++-verzióban is javította pl.) illetve volt egy kis gond a castolással, ezt a hallgató maga javította (illetve kisbajnokságért másik hallgatónak is sikerült)

borokcs 2011.04.21. 10:32:01

#include <iostream>
#include <cmath>
#include <fstream>

class LZWBinFa
{
public:

LZWBinFa (): fa(&gyoker) {}

void operator<<(char b)
{

if (b == '0')
{

if (!fa->nullasGyermek ()) // ha nincs, hát akkor csinálunk
{

Csomopont *uj = new Csomopont ('0');
fa->ujNullasGyermek (uj);
fa = &gyoker;
}
else
{
fa = fa->nullasGyermek ();
}
}

else
{
if (!fa->egyesGyermek ())
{
Csomopont *uj = new Csomopont ('1');
fa->ujEgyesGyermek (uj);
fa = &gyoker;
}
else
{
fa = fa->egyesGyermek ();
}
}
}

void kiir (void)
{

melyseg = 0;

kiir (&gyoker, std::cout);
}
void szabadit (void)
{
szabadit (gyoker.egyesGyermek());
szabadit (gyoker.nullasGyermek());

}

int getMelyseg (void);
double getAtlag (void);
double getSzoras (void);

friend std::ostream& operator<< (std::ostream& os, LZWBinFa& bf)
{
bf.kiir(os);
return os;
}
void kiir (std::ostream& os)
{
melyseg = 0;
kiir (&gyoker, os);
}

private:
class Csomopont
{
public:

Csomopont (char b = '/'):betu (b), balNulla (0), jobbEgy (0) {};
~Csomopont () {};

Csomopont *nullasGyermek () const {
return balNulla;
}

Csomopont *egyesGyermek () const {
return jobbEgy;
}

void ujNullasGyermek (Csomopont * gy) {
balNulla = gy;
}

void ujEgyesGyermek (Csomopont * gy) {
jobbEgy = gy;
}

char getBetu() const {
return betu;
}

private:

char betu;

Csomopont *balNulla;
Csomopont *jobbEgy;

Csomopont (const Csomopont &);
Csomopont & operator=(const Csomopont &);
};

Csomopont *fa;

int melyseg, atlagosszeg, atlagdb;
double szorasosszeg;

LZWBinFa (const LZWBinFa &);
LZWBinFa & operator=(const LZWBinFa &);

void kiir (Csomopont* elem, std::ostream& os)
{

if (elem != NULL)
{
++melyseg;
kiir (elem->egyesGyermek(), os);

for (int i = 0; i < melyseg; ++i)
os << "---";
os << elem->getBetu() << "(" << melyseg - 1 << ")" << std::endl;
kiir (elem->nullasGyermek(), os);
--melyseg;
}
}
void szabadit (Csomopont * elem)
{

if (elem != NULL)
{
szabadit (elem->egyesGyermek());
szabadit (elem->nullasGyermek());

delete elem;
}
}

protected:

Csomopont gyoker;
int maxMelyseg;
double atlag, szoras;

void rmelyseg (Csomopont* elem);
void ratlag (Csomopont* elem);
void rszoras (Csomopont* elem);

};

int LZWBinFa::getMelyseg (void)
{
melyseg = maxMelyseg = 0;
rmelyseg (&gyoker);
return maxMelyseg-1;
}
double LZWBinFa::getAtlag (void)
{
melyseg = atlagosszeg = atlagdb = 0;
ratlag (&gyoker);
atlag = ((double)atlagosszeg) / atlagdb;
return atlag;
}
double LZWBinFa::getSzoras (void)
{
atlag = getAtlag ();
szorasosszeg = 0.0;
melyseg = atlagdb = 0;

rszoras (&gyoker);

if (atlagdb - 1 > 0)
szoras = std::sqrt( szorasosszeg / (atlagdb - 1));
else
szoras = std::sqrt (szorasosszeg);

return szoras;
}
void LZWBinFa::rmelyseg (Csomopont* elem)
{
if (elem != NULL)
{
++melyseg;
if (melyseg > maxMelyseg)
maxMelyseg = melyseg;
rmelyseg (elem->egyesGyermek());
rmelyseg (elem->nullasGyermek());
--melyseg;
}
}
void
LZWBinFa::ratlag (Csomopont* elem)
{
if (elem != NULL)
{
++melyseg;
ratlag (elem->egyesGyermek());
ratlag (elem->nullasGyermek());
--melyseg;
if (elem->egyesGyermek() == NULL && elem->nullasGyermek() == NULL)
{
++atlagdb;
atlagosszeg += melyseg;
}
}
}
void
LZWBinFa::rszoras (Csomopont* elem)
{
if (elem != NULL)
{
++melyseg;
rszoras (elem->egyesGyermek());
rszoras (elem->nullasGyermek());
--melyseg;
if (elem->egyesGyermek() == NULL && elem->nullasGyermek() == NULL)
{
++atlagdb;
szorasosszeg += ((melyseg - atlag) * (melyseg - atlag));
}
}
}

int
main ()
{
char b;
LZWBinFa binFa;

while (std::cin >> b)
{
binFa << b;
}

std::cout << binFa;

std::cout << "depth = " << binFa.getMelyseg () << std::endl;
std::cout << "mean = " << binFa.getAtlag () << std::endl;
std::cout << "var = " << binFa.getSzoras () << std::endl;

binFa.szabadit ();

return 0;
}

void usage(void)
{
std::cout << "Usage: lzwtree in_file -o out_file" << std::endl;
}

int
main (int argc, char *argv[])
{

if (argc != 4) {

usage();

return -1;
}

char *inFile = *++argv;

if (*((*++argv)+1) != 'o') {
usage();
return -2;
}

std::fstream beFile (inFile, std::ios_base::in);
std::fstream kiFile (*++argv, std::ios_base::out);

unsigned char b;
LZWBinFa binFa;

while (beFile.read ((char *) &b, sizeof (unsigned char))) {

for (int i = 0; i < 8; ++i)
{
int egy_e = b & 0x80;

if ((egy_e >> 7) == 1)

binFa << '1';
else

binFa << '0';
b <<= 1;
}

}

kiFile << binFa;

kiFile << "depth = " << binFa.getMelyseg () << std::endl;
kiFile << "mean = " << binFa.getAtlag () << std::endl;
kiFile << "var = " << binFa.getSzoras () << std::endl;

binFa.szabadit ();

kiFile.close();
beFile.close();

return 0;
}

nb · http://fersml.blog.hu 2011.04.23. 20:17:50

@borokcs: mi a kérdés, vagy ez mire a válasz?

:)
süti beállítások módosítása