Kompresja tekstu stratnego

9

tło

Z 256 możliwych znaków, które bajt może reprezentować, tylko kilka z nich jest używanych w większości przypadków. Czy nie moglibyśmy w jakiś sposób skorzystać z tego i zmniejszyć nasze pliki tekstowe, eliminując potrzebę korzystania z rzadko używanych liter?

Wiele liter nie dodaje żadnej wartości w większości sytuacji i można je zastąpić bardziej popularnymi literami. Na przykład małe litery „L”, wielkie „I” i cyfra „1” wyglądają prawie identycznie w większości sytuacji, więc można je skonsolidować.

Duże litery nie są potrzebne, więc można je pominąć. Program do dekompresji / wyświetlania może nawet automatycznie zamieniać pierwszą literę każdego zdania, nazwy pospolite itp.

Zasady

Zgłoszenia będą oceniane na:

  • Stopień sprężania
  • czytelność po dekompresji

Wpisy będą testowane pod kątem wersji tekstowej tego artykułu: http://en.wikipedia.org/wiki/Babbage oraz losowo wybranego artykułu BBC News .

Dodatkowe oceny zostaną przyznane; zachowując wszelkie narzuty, upiększając po dekompresji (np. zdania wielkie litery itp.).

Języki

  • Jak tylko chcesz, ale musisz łatwo skompilować (lub zinterpretować) na podstawowym * polu nix.
Richard Stelling
źródło
Więc PowerShell jest niedostępny? Porażka.
Joey,
1
Haskell:main = interact (\x -> take 90 x ++ " yada yada yada")
Joey Adams,
1
Należy również zauważyć, że „czytelność po dekompresji” jest dość subiektywnym kryterium.
Joey,
Zwłaszcza na Unix-Box potrzebujemy rozróżnienia wielkich i małych liter. :) I znalezienie początku wysłanego. Nie jest trywialne, jeśli u. Używa skrótu! :)
użytkownik nieznany
Czy chcemy skompresować alfabet lub tekst? :) L = l = 1 kompresuje znaki potrzebne do przedstawienia naszych myśli. Ale „jedno jabłko” = „1 apl” kompresuje tekst.
anemgyenge

Odpowiedzi:

11

Perl

Bardzo nieefektywny i ma złe stawki. Wymaga /usr/share/dict/words.

Kompresor

#!/usr/bin/perl

$M = 2;
$N = 1;
$Min = 3;
$Max = 8;

while (<>) {
  for (split /\s+/) {
    s/[^a-z]//i;
    ($p) = m/([^a-z]*)$/;
    $_ = lc $_;
    $l = (length $_) - (length $p);
    s/^and$/A/;
    s/^he$/H/;
    s/^in$/I/;
    s/^of$/O/;
    s/^you$/U/;
    s/^the$/Z/;
    if (length $_ >= $Min) {
      if (length $_ <= $Max) {
        s/ed/D/g;
        s/ing\b/N/g;
        s/er/R/g;
        s/'s/S/g;
        s/th/T/g;
        s/[aeo]{1,2}//g;
        $_ .= $l;
      } else {
        s/^(.{$M})(.+)(\w{$N})$/$1.(length$2).$3/e;
      }
    }
    $a .= $_ . $p . ' ';
  }
}
print $a;

Dekompresor

#!/usr/bin/perl

$M = 2;
$N = 1;

open D, '/usr/share/dict/words';
chomp, push @W, $_ while <D>;
close D;

while (<>) {
  for (split /\s+/) {
    ($_, $p) = m/^(.+)([^a-z]*)$/;
    s/^A$/and/;
    s/^H$/he/;
    s/^I$/in/;
    s/^O$/of/;
    s/^U$/you/;
    s/^Z$/the/;
    if ($_ =~ m/^(\w{$M})(\d+)(\w{$N})$/) {
      $r = '^' . quotemeta($1) . ('\w' x $2) . quotemeta($3) . '$';
      ($_) = (grep /$r/, @W);
      $_ .= $4;
    } else {
      ($_, $l) = m/^(.+)(\d+)$/;
      s/D/ed/g;
      s/N/ing/g;
      s/R/er/g;
      s/S/'s/g;
      s/T/th/g;
      $r = '[aeo]{0,2}';
      for $y(split //) { $r .= (quotemeta $y) . '[aiueo]{0,2}' }
      ($_) = (grep /^(?=[a-z]{$l})$r$/, @W);
    }
    $a .= $_ . $p . ' ';
  }
}
print $a;
Ming-Tang
źródło
3

Perl, 0 znaków

Współczynnik kompresji nieskończoności, choć nie tak czytelny po dekompresji, więc straci niektóre znaki.

Ry-
źródło
2

Bash, 5 znaków

Mój leniwy wpis, który może wygrać:

bzip2

Bezstratny, więc doskonale zachowuje czytelność i otrzymuje wszystkie dodatkowe znaki! Współczynnik kompresji html Babbage'a wynosi 4,79x (153804 do 32084 bajtów).

Keith Randall
źródło
Jakoś wiedziałem, że nadchodzi z tym wyzwaniem ;-)
Joey,
Trudno będzie to pokonać.
Lowjacker 18.04.11.04
Hah! Pokonałem go zarówno pod względem długości, jak i stopnia kompresji;)
Ry-
2
xz, jeszcze krótszy i lepszy stosunek :)
OneOfOne 24.04.2011