{"id":347,"date":"2017-05-14T23:00:55","date_gmt":"2017-05-14T21:00:55","guid":{"rendered":"http:\/\/antek.atthost24.pl\/?p=347"},"modified":"2017-05-14T23:00:55","modified_gmt":"2017-05-14T21:00:55","slug":"czas-na-troche-kompresji","status":"publish","type":"post","link":"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/","title":{"rendered":"Czas na troch\u0119 kompresji!"},"content":{"rendered":"<p>W <a href=\"http:\/\/antek.atthost24.pl\/index.php\/2017\/04\/12\/tokenizacja-kodu-zrodlowego\/\">poprzednim wpisie<\/a> na temat PlagDetectora opisali\u015bmy tokenizacje kodu \u017ar\u00f3d\u0142owego. By\u0142 to pierwszy z trzech etap\u00f3w ca\u0142ego algorytmu. Dzisiaj zajmiemy si\u0119 drugim krokiem, czyli kompresj\u0105 token\u00f3w.<\/p>\n<h3>Kilka s\u0142\u00f3w o samej kompresji<\/h3>\n<p>Kompresja, jak sama nazwa wskazuje ;), jest to przetworzenie pewnej informacji w taki spos\u00f3b, aby mo\u017cna by\u0142o zapisa\u0107 t\u0105 informacje w <em>kr\u00f3tszy<\/em> spos\u00f3b. Przez s\u0142owo <em>kr\u00f3tszy<\/em> mam na my\u015bli przy u\u017cyciu mniejszej ilo\u015bci bajt\u00f3w. Operacj\u0105 odwrotn\u0105 do kompresji jest dekompresja.<\/p>\n<h4>Rodzaje kompresji<\/h4>\n<p>Kompresje mo\u017cemy podzieli\u0107 na stratn\u0105 oraz bezstratn\u0105. Jak sama nazwa wskazuje, w przypadku kompresji stratnej tracimy cz\u0119\u015b\u0107 informacji, dzi\u0119ki czemu powinni\u015bmy uzyska\u0107 wi\u0119kszy wsp\u00f3\u0142czynnik kompresji (przynajmniej w teorii ;)).<\/p>\n<p>Oczywi\u015bcie istnieje wiele algorytm\u00f3w kompresji, kt\u00f3re mo\u017cemy przyporz\u0105dkowa\u0107 do kompresji stratnej lub bezstratnej.<\/p>\n<p>Sp\u00f3jrzmy na poni\u017cszy podzia\u0142 algorytm\u00f3w.<\/p>\n<ul>\n<li>Kompresja bezstratna\n<ul>\n<li>Kodowanie Huffmana<\/li>\n<li>Kodowanie arytmetyczne<\/li>\n<li>Kodowanie Shannona<\/li>\n<li>Algorytmy s\u0142ownikowe\n<ul>\n<li>LZ77<\/li>\n<li>LZ78<\/li>\n<li>LZW<\/li>\n<\/ul>\n<\/li>\n<li>PNG<\/li>\n<\/ul>\n<\/li>\n<li>Kompresja stratna\n<ul>\n<li>Kodowanie transformatowe<\/li>\n<li>Kompresja falkowa<\/li>\n<li>JPEG<\/li>\n<li>MPEG<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Oczywi\u015bcie to nie s\u0105 wszystkie istniej\u0105ce algorytmy kompresji, ale wydaj\u0119 mi si\u0119, \u017ce te najbardziej znane \ud83d\ude42<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-351 aligncenter\" src=\"http:\/\/antek.atthost24.pl\/wp-content\/uploads\/2017\/05\/which_one.png\" alt=\"\" width=\"500\" height=\"286\" srcset=\"https:\/\/blog.lantkowiak.pl\/wp-content\/uploads\/2017\/05\/which_one.png 500w, https:\/\/blog.lantkowiak.pl\/wp-content\/uploads\/2017\/05\/which_one-300x172.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<h3>Kt\u00f3ry algorytm wybra\u0107?<\/h3>\n<p>Jak widzieli\u015bmy, jest wiele algorytm\u00f3w kompresji bezstratnej. Kt\u00f3ry zatem powinni\u015bmy wybra\u0107? Sugeruj\u0105c si\u0119 tym co wybrali tw\u00f3rcy algorytmu SID (opisanym w jednym z poprzednich wpis\u00f3w), r\u00f3wnie\u017c skupimy si\u0119 na kodowaniu s\u0142ownikowym, a konkretnie LZ77. Czemu w\u0142asnie LZ77, a nie \u017caden z innych algorytm\u00f3w kodowania s\u0142ownikowego jak LZ78 czy LZW, kt\u00f3re s\u0105 rozwini\u0119ciem LZ77 (i cz\u0119sto dzia\u0142aj\u0105 lepiej)? Zaraz wszystko powinno si\u0119 wyja\u015bni\u0107 \ud83d\ude42<\/p>\n<h3>Troch\u0119 teorii \ud83d\ude42<\/h3>\n<p>Sp\u00f3jrzmy najpierw jak dzia\u0142a LZ77.<\/p>\n<p>Jak wcze\u015bniej wspomnieli\u015bmy, LZ77 jest algorytmem s\u0142ownikowym? Znaczy to dok\u0142adnie tyle, \u017ce do zakodowania\/odkodowania tekstu u\u017cywamy s\u0142ownika. W LZ77 s\u0142ownik jest dynamiczny, czyli taki s\u0142ownik, kt\u00f3ry jest tworzony w trakcie kodowania. S\u0142ownik tego typu ma r\u00f3wnie\u017c t\u0119 zalet\u0119, \u017ce dostosowuje si\u0119 do charakteru danych. W LZ77 s\u0142ownikiem jest zakodowana\/odkodowana cz\u0119\u015b\u0107 tekstu.<\/p>\n<p>I teraz sam algorytm w teorii:<\/p>\n<ul>\n<li>Dla zakodowanej cz\u0119\u015bci d\u0142ugo\u015bci n i niezakodowanej d\u0142ugo\u015bci m, czyli dla ci\u0105gu <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lantkowiak.pl\/wp-content\/ql-cache\/quicklatex.com-e805ab4e0087debce1d242f4cfdf9cf4_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#123;&#120;&#95;&#49;&#32;&#92;&#108;&#100;&#111;&#116;&#115;&#32;&#120;&#95;&#110;&#120;&#95;&#123;&#110;&#43;&#49;&#125;&#32;&#92;&#108;&#100;&#111;&#116;&#115;&#32;&#120;&#95;&#123;&#110;&#43;&#109;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"13\" width=\"168\" style=\"vertical-align: -5px;\"\/> szukamy najd\u0142u\u017cszego pods\u0142owa w ci\u0105gu \u0307 <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lantkowiak.pl\/wp-content\/ql-cache\/quicklatex.com-6987e02cff3c8a009d0fd627829aad9f_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#123;&#120;&#95;&#49;&#32;&#92;&#108;&#100;&#111;&#116;&#115;&#32;&#120;&#95;&#110;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"62\" style=\"vertical-align: -4px;\"\/> b\u0119d\u0105cego prefiksem ci\u0105gu <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lantkowiak.pl\/wp-content\/ql-cache\/quicklatex.com-5b6a057315e9f80bb0ff290affa5afc0_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#123;&#120;&#95;&#123;&#110;&#43;&#49;&#125;&#32;&#92;&#108;&#100;&#111;&#116;&#115;&#32;&#120;&#95;&#123;&#110;&#43;&#109;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"13\" width=\"104\" style=\"vertical-align: -5px;\"\/> (dopasowanie).<\/li>\n<li>Jako kod podajemy trzy liczby:\n<ul>\n<li>wielko\u015b\u0107 przesuni\u0119cia w lewo<\/li>\n<li>ilo\u015b\u0107 kopiowanych znak\u00f3w<\/li>\n<li>kod pierwszej niepasuj\u0105cej litery<\/li>\n<\/ul>\n<\/li>\n<li>Je\u017celi pojawia si\u0119 nowa litera, kt\u00f3rej nie mo\u017cna znale\u017a\u0107 w zakodowanej cz\u0119\u015bci to do s\u0142ownika dodajemy <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.lantkowiak.pl\/wp-content\/ql-cache\/quicklatex.com-adc1bad82b6f94c85332421ef7cc3e2f_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#123;&#40;&#48;&#44;&#32;&#48;&#44;&#32;&#76;&#73;&#84;&#69;&#82;&#65;&#41;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"18\" width=\"120\" style=\"vertical-align: -4px;\"\/><\/li>\n<\/ul>\n<p>Brzmi skomplikowanie, ale przyk\u0142ad powinien nam wszystko wyja\u015bni\u0107 \ud83d\ude42<\/p>\n<p>Najpierw ustalmy nasze <span style=\"color: #ff0000;\">n<\/span>\u00a0(bufor s\u0142ownika) i <span style=\"color: #0000ff;\">m\u00a0<\/span>(bufor kodowania). Przyjmijmy odpowiednio 7 i 8. Spr\u00f3bujmy teraz zakodowa\u0107 nast\u0119puj\u0105cy ci\u0105g: <em>abccba-abba<\/em>.<\/p>\n<ul>\n<li><span style=\"color: #0000ff;\">abccba-a<\/span>bba \u00a0 \u00a0<span style=\"color: #339966;\">(0, 0, a)<\/span><\/li>\n<li><span style=\"color: #ff0000;\">a<\/span><span style=\"color: #0000ff;\">bccba-ab<\/span>ba \u00a0 \u00a0<span style=\"color: #339966;\">(0, 0, b)<\/span><\/li>\n<li><span style=\"color: #ff0000;\">ab<\/span><span style=\"color: #0000ff;\">ccba-abb<\/span>a \u00a0 \u00a0<span style=\"color: #339966;\">(0, 0, c)<\/span><\/li>\n<li><span style=\"color: #ff0000;\">abc<\/span><span style=\"color: #0000ff;\">cba-abba<\/span> \u00a0 \u00a0<span style=\"color: #339966;\">(1, 1, b)<\/span><\/li>\n<li><span style=\"color: #ff0000;\">abccb<\/span><span style=\"color: #0000ff;\">a-abba<span style=\"color: #000000;\"> \u00a0 \u00a0<span style=\"color: #339966;\">(5, 1, -)<\/span><\/span><\/span><\/li>\n<li><span style=\"color: #ff0000;\">abccba-<\/span><span style=\"color: #0000ff;\">abba<\/span> \u00a0 \u00a0<span style=\"color: #339966;\">(7, 2, b)<\/span><\/li>\n<li>ab<span style=\"color: #ff0000;\">ccba-abb<\/span><span style=\"color: #0000ff;\">a<\/span> \u00a0 \u00a0<span style=\"color: #339966;\">(0, 0, a)<\/span><\/li>\n<\/ul>\n<p>Zatem ostatecznie nasz zakodowany ci\u0105g ma posta\u0107 powy\u017cszych siedmiu 'tr\u00f3jek&#8217;, czyli:\u00a0(0, 0, a), (0, 0, b), (0, 0, c), (1, 1, b), (5, 1, -), (7, 2, b), (0, 0, a).<\/p>\n<h4>Czemu w\u0142a\u015bnie LZ77?<\/h4>\n<p>I teraz wracamy do kwestii wyboru algorytmu. Dlaczego w\u0142a\u015bnie LZ77? Tak jak pisali\u015bmy w jednym z <a href=\"http:\/\/antek.atthost24.pl\/index.php\/2017\/04\/04\/wykrywanie-plagiatow-wybor-algorytmu\/\">poprzednich wpis\u00f3w<\/a>, musimy ustawi\u0107 niesko\u0144czony bufor s\u0142ownika i bufor kodowania. Wi\u0105\u017c\u0119 si\u0119 to oczywi\u015bcie z wyd\u0142u\u017ceniem czasu kompresji, ale dzi\u0119ki temu mo\u017cemy uzyska\u0107 wi\u0119kszy stopie\u0144 kompresji.<\/p>\n<p>W tym samum wpisie, w kolejnej sekcji, jest opisana cz\u0119\u015b\u0107 z aproksymacj\u0105 z\u0142o\u017cono\u015bci Ko\u0142mogorowa. W jednym ze wzor\u00f3w mo\u017cemy dopatrze\u0107 si\u0119, \u017ce kompresji b\u0119dzie r\u00f3wnie\u017c poddana lista sk\u0142adaj\u0105ca si\u0119 z token\u00f3w z dw\u00f3ch por\u00f3wnywanych kod\u00f3w \u017ar\u00f3d\u0142owych. Jakie to ma znaczenie przy wyborze algorytmu kompresji?<\/p>\n<p>Wr\u00f3\u0107my do naszego przyk\u0142adu i zastan\u00f3wmy si\u0119 co by si\u0119 sta\u0142o jakby\u015bmy przyj\u0119li, \u017ce n i m s\u0105 niesko\u0144czone oraz mieli do zakodowania ci\u0105g:\u00a0<em>abccba-abbaabccba-abba\u00a0<\/em>(podwojony ci\u0105g z naszego przyk\u0142adu).<\/p>\n<p>Pierwsze sze\u015b\u0107 krok\u00f3w kodowania wygl\u0105da identycznie, wi\u0119c mo\u017cemy zacz\u0105\u0107 ten przyk\u0142ad od w\u0142asnie sz\u00f3stego kroku.<\/p>\n<ul>\n<li><span style=\"color: #ff0000;\">abccba-<\/span><span style=\"color: #0000ff;\">abbaabccba-abba<\/span> \u00a0 \u00a0<span style=\"color: #339966;\">(7, 2, b)<\/span><\/li>\n<li><span style=\"color: #ff0000;\">abccba-<\/span><span style=\"color: #0000ff;\"><span style=\"color: #ff0000;\">abb<\/span>aabccba-abba<\/span> \u00a0 \u00a0<span style=\"color: #339966;\">(3, 1, a)<\/span><\/li>\n<li><span style=\"color: #ff0000;\">abccba-<\/span><span style=\"color: #0000ff;\"><span style=\"color: #ff0000;\">abbaa<\/span>bccba-abba<\/span> \u00a0 \u00a0<span style=\"color: #339966;\">(11, 9, a)<\/span><\/li>\n<\/ul>\n<p>Zauwa\u017cmy, \u017ce do zakodowaniu podwojonego ci\u0105gu potrzebowali\u015bmy tylko jednej 'tr\u00f3jki&#8217; wi\u0119cej. I to jest w\u0142asnie w\u0142a\u015bciwo\u015b\u0107, na kt\u00f3rej nam zale\u017cy, a kt\u00f3rej nie maj\u0105 LZ78 i LZW. Chcemy wykrywa\u0107 plagiaty, wi\u0119c powinni\u015bmy za\u0142o\u017cy\u0107, \u017ce tokeny por\u00f3wnywanych kod\u00f3w \u017ar\u00f3d\u0142owych mog\u0105 by\u0107 takie same lub bardzo podobne ;).<\/p>\n<h3>I troch\u0119 praktyki!<\/h3>\n<p>I w ko\u0144cu troch\u0119 kodu! \ud83d\ude42<\/p>\n<p>Zacznijmy od stworzenia klasy, kt\u00f3ra b\u0119dzie nam reprezentowa\u0107 zakodowan\u0105 'tr\u00f3jk\u0119&#8217;.<\/p>\n<pre class=\"lang:default decode:true \">data class CodedTriple&lt;T&gt;(val shift: Int, val length: Int, val next: T)<\/pre>\n<p>Bana\u0142 \ud83d\ude09<\/p>\n<p>Teraz niestety troch\u0119 magii&#8230;<\/p>\n<pre class=\"lang:default decode:true\">package pl.lantkowiak.plagdetector.algorithm.compressor\r\n\r\nclass Compressor&lt;T&gt; {\r\n    fun encode(input: List&lt;T&gt;): List&lt;CodedTriple&lt;T&gt;&gt; {\r\n        \/\/ tworzymy liste, do ktorej bedziemy dodawac nasze 'trojki'\r\n        val coded = mutableListOf&lt;CodedTriple&lt;T&gt;&gt;()\r\n        \/\/ dodajemy pierwsza 'trojke' zawierajaca pierwszy znak z wejscia\r\n        coded.add(CodedTriple(0, 0, input[0]))\r\n\r\n        var i = 1;\r\n        while (i &lt; input.size) {\r\n            \/\/ pobieramy bufor slownika\r\n            val dictionary = this.getDictionary(i, input)\r\n            \/\/ znajdujemy najdluzsze dopasowanie ze slownika\r\n            val codedTriple = this.findLongestPrefix(i, input, dictionary)\r\n            \/\/ dodajemy znaleziona 'trojke'\r\n            coded.add(codedTriple)\r\n            \/\/ przesuwamy wskaznik pozycji\r\n            i += codedTriple.length + 1\r\n        }\r\n\r\n        return coded\r\n    }\r\n\r\n    private fun getDictionary(index: Int, input: List&lt;T&gt;): List&lt;T&gt; {\r\n        return input.subList(0, index)\r\n    }\r\n\r\n    private fun findLongestPrefix(position: Int, input: List&lt;T&gt;, dictionary: List&lt;T&gt;): CodedTriple&lt;T&gt; {\r\n        var i = position + 1\r\n        var last = ShiftLength(0, 0)\r\n        var positionLength = this.findSequence(input.subList(position, i), dictionary)\r\n\r\n        while (i &lt; input.size &amp;&amp; positionLength.shift &gt; 0) {\r\n            i++\r\n            last = positionLength\r\n            positionLength = this.findSequence(input.subList(position, i), dictionary)\r\n        }\r\n        return CodedTriple(last.shift, last.length, input[position + last.length])\r\n    }\r\n\r\n    \/\/ naive algorithm is used... it is slow...\r\n    private fun findSequence(sequence: List&lt;T&gt;, dictionary: List&lt;T&gt;): ShiftLength {\r\n        var found = false\r\n\r\n        for (i in 0 until dictionary.size) {\r\n            for (j in 0 until sequence.size) {\r\n                if (sequence[j] != (this.getDictionaryElement(i + j, dictionary))) {\r\n                    found = false\r\n                    break\r\n                } else {\r\n                    found = true\r\n                }\r\n            }\r\n            if (found) {\r\n                return ShiftLength(dictionary.size - i, sequence.size)\r\n            }\r\n        }\r\n\r\n        return ShiftLength(0, 0)\r\n    }\r\n\r\n\r\n    private fun getDictionaryElement(position: Int, dictionary: List&lt;T&gt;): T {\r\n        return dictionary[position % dictionary.size]\r\n    }\r\n\r\n    data class ShiftLength(val shift: Int, val length: Int)\r\n}<\/pre>\n<p>Powy\u017cej zaimplementowali\u015bmy algorytm LZ77 z nieograniczonym buforem s\u0142ownika i kodowania. U\u017cyty algorytm jest\u00a0napisany dosy\u0107 'prostacko&#8217;, ale dzia\u0142a \ud83d\ude42 Przy najbli\u017cszej okazji wr\u00f3cimy do niego i go zrefaktorujemy \ud83d\ude09<\/p>\n<h3>Podsumowanie<\/h3>\n<p>Dzisiaj zaj\u0119li\u015bmy si\u0119 drugim etapem w naszym algorytmie do wykrywania plagiat\u00f3w., a mianowicie kompresj\u0105 token\u00f3w. Zobaczyli\u015bmy jak wygl\u0105da LZ77 i zobaczyli\u015bmy jak dzia\u0142a. Na koniec w troch\u0119 prostacki spos\u00f3b zaimplementowali\u015bmy LZ77 z nieograniczonym buforem s\u0142ownikowym i kodowania w Kotlinie ;). W nast\u0119pnym wpisie zwi\u0105zanym z PlagDetectorem zajmiemy si\u0119 trzecim etapem czyli aproksymacj\u0105 z\u0142o\u017cono\u015bci Ko\u0142mogorowa \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>W poprzednim wpisie na temat PlagDetectora opisali\u015bmy tokenizacje kodu \u017ar\u00f3d\u0142owego. By\u0142 to pierwszy z trzech etap\u00f3w ca\u0142ego algorytmu. Dzisiaj zajmiemy si\u0119 drugim krokiem, czyli kompresj\u0105 token\u00f3w. Kilka s\u0142\u00f3w&#8230;<\/p>\n","protected":false},"author":1,"featured_media":348,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,19],"tags":[],"class_list":["post-347","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dsp2017","category-plagdetector"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Czas na troch\u0119 kompresji! - Lukasz Antkowiak&#039;s blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/\" \/>\n<meta property=\"og:locale\" content=\"pl_PL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Czas na troch\u0119 kompresji! - Lukasz Antkowiak&#039;s blog\" \/>\n<meta property=\"og:description\" content=\"W poprzednim wpisie na temat PlagDetectora opisali\u015bmy tokenizacje kodu \u017ar\u00f3d\u0142owego. By\u0142 to pierwszy z trzech etap\u00f3w ca\u0142ego algorytmu. Dzisiaj zajmiemy si\u0119 drugim krokiem, czyli kompresj\u0105 token\u00f3w. Kilka s\u0142\u00f3w...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukasz Antkowiak&#039;s blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-05-14T21:00:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.lantkowiak.pl\/wp-content\/uploads\/2017\/05\/datacompression2012.png\" \/>\n\t<meta property=\"og:image:width\" content=\"577\" \/>\n\t<meta property=\"og:image:height\" content=\"256\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"\u0141ukasz Antkowiak\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Napisane przez\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u0141ukasz Antkowiak\" \/>\n\t<meta name=\"twitter:label2\" content=\"Szacowany czas czytania\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minut\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/\",\"url\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/\",\"name\":\"Czas na troch\u0119 kompresji! - Lukasz Antkowiak&#039;s blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.lantkowiak.pl\/#website\"},\"datePublished\":\"2017-05-14T21:00:55+00:00\",\"dateModified\":\"2017-05-14T21:00:55+00:00\",\"author\":{\"@id\":\"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/#breadcrumb\"},\"inLanguage\":\"pl-PL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Strona g\u0142\u00f3wna\",\"item\":\"https:\/\/blog.lantkowiak.pl\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Czas na troch\u0119 kompresji!\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/#website\",\"url\":\"https:\/\/blog.lantkowiak.pl\/\",\"name\":\"Lukasz Antkowiak&#039;s blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.lantkowiak.pl\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pl-PL\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6\",\"name\":\"\u0141ukasz Antkowiak\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pl-PL\",\"@id\":\"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g\",\"caption\":\"\u0141ukasz Antkowiak\"},\"description\":\"dd\",\"url\":\"https:\/\/blog.lantkowiak.pl\/index.php\/author\/antek\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Czas na troch\u0119 kompresji! - Lukasz Antkowiak&#039;s blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/","og_locale":"pl_PL","og_type":"article","og_title":"Czas na troch\u0119 kompresji! - Lukasz Antkowiak&#039;s blog","og_description":"W poprzednim wpisie na temat PlagDetectora opisali\u015bmy tokenizacje kodu \u017ar\u00f3d\u0142owego. By\u0142 to pierwszy z trzech etap\u00f3w ca\u0142ego algorytmu. Dzisiaj zajmiemy si\u0119 drugim krokiem, czyli kompresj\u0105 token\u00f3w. Kilka s\u0142\u00f3w...","og_url":"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/","og_site_name":"Lukasz Antkowiak&#039;s blog","article_published_time":"2017-05-14T21:00:55+00:00","og_image":[{"width":577,"height":256,"url":"https:\/\/blog.lantkowiak.pl\/wp-content\/uploads\/2017\/05\/datacompression2012.png","type":"image\/png"}],"author":"\u0141ukasz Antkowiak","twitter_card":"summary_large_image","twitter_misc":{"Napisane przez":"\u0141ukasz Antkowiak","Szacowany czas czytania":"6 minut"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/","url":"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/","name":"Czas na troch\u0119 kompresji! - Lukasz Antkowiak&#039;s blog","isPartOf":{"@id":"https:\/\/blog.lantkowiak.pl\/#website"},"datePublished":"2017-05-14T21:00:55+00:00","dateModified":"2017-05-14T21:00:55+00:00","author":{"@id":"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6"},"breadcrumb":{"@id":"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/#breadcrumb"},"inLanguage":"pl-PL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.lantkowiak.pl\/index.php\/2017\/05\/14\/czas-na-troche-kompresji\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Strona g\u0142\u00f3wna","item":"https:\/\/blog.lantkowiak.pl\/"},{"@type":"ListItem","position":2,"name":"Czas na troch\u0119 kompresji!"}]},{"@type":"WebSite","@id":"https:\/\/blog.lantkowiak.pl\/#website","url":"https:\/\/blog.lantkowiak.pl\/","name":"Lukasz Antkowiak&#039;s blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.lantkowiak.pl\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pl-PL"},{"@type":"Person","@id":"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/009bfc4db220c225786c59b1748ba1e6","name":"\u0141ukasz Antkowiak","image":{"@type":"ImageObject","inLanguage":"pl-PL","@id":"https:\/\/blog.lantkowiak.pl\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e18e2bfe319da9b5757cf7f7ae1bfecf?s=96&d=monsterid&r=g","caption":"\u0141ukasz Antkowiak"},"description":"dd","url":"https:\/\/blog.lantkowiak.pl\/index.php\/author\/antek\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts\/347","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/comments?post=347"}],"version-history":[{"count":9,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts\/347\/revisions"}],"predecessor-version":[{"id":358,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/posts\/347\/revisions\/358"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/media\/348"}],"wp:attachment":[{"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/media?parent=347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/categories?post=347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lantkowiak.pl\/index.php\/wp-json\/wp\/v2\/tags?post=347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}