Kayıpsız İngilizce metin sıkıştırma zorluğu [kapalı]


12

Meydan okuma:

Zorluğunuz (kabul etmeyi seçmeniz gerekir), burada bulunan 5MB " William Shakespeare'in Tamamlanmış İşleri " ni sıkıştırmak ve açmaktır : http://www.gutenberg.org/cache/epub/100/pg100.txt

(MD5: a810f89e9f8e213aebd06b9f8c5157d8)

Kurallar:

  • Üzerinden giriş ve çıkış yoluyla almak gerekir ...STDINSTDOUT
  • ... ve girişe aynı sıkıştırılmış sonucu vermelisiniz .
    • (Bu, yukarıdaki ile aynı MD5'i alabilmeniz ve alabilmeniz gerektiği anlamına gelir.)cat inpt.txt | ./cmprss | ./dcmpress | md5
    • (Üzerinden herhangi bir şey STDERRatılmalıdır.)
  • Sen gerekir toplam kaynak kodu için 2048 karakterleri kullanın.
    • (Bu değil kod golf. Sen edilir değil kaynak kodunun uzunluğuna göre puan ediliyor. Bu ise sonlu şeyleri tutmak için sadece bir kural oldu.)
    • (Ayırdıysanız, tüm kaynak kodun birleştirilmiş uzunluğunu alın.)
  • Sen gerekir çok (teorik olarak) işlem benzer düz metin girişlerine mümkün.
    • (örneğin, yalnızca sağlanan Shakespeare girdisini çıktılayabilen bir mekanizmanın sabit kodlanması kabul edilemez.)
    • (Sıkıştırılmış sonucun alternatif girdi ile aynı olması koşuluyla, diğer belgelerin sıkıştırılmış boyutu önemsizdir.)
  • Sen edebilir dil (s) herhangi bir seçim kullanın.
    • (örn. kullanarak sıkıştırmaktan çekinmeyin awkve kullanarak sıkıştırmasını açın java)
  • İstediğiniz gibi iki ayrı program yazabilir veya bir çeşit "anahtar" ile birleştirebilirsiniz.
    • (Hem sıkıştırma hem de dekompresyon modlarının nasıl çağrılacağına dair net gösteriler olmalıdır)
  • Sen olabilir değil herhangi bir harici komutları (örn üzerinden kullanmak exec()).
    • (Eğer bir kabuk dili kullanıyorsanız - üzgünüm. )
  • Sen olabilir değil (gibi kompres verilere olan amacını dile getirilmiştir herhangi bir yerleşik veya kütüphane sağlanan işlevleri kullanmak gzvb)
    • (Kodlamanın değiştirilmesi bu bağlamda sıkıştırma olarak kabul edilmez. Burada bir miktar takdir yetkisi olabilir.
  • Katılmayı seçerseniz lütfen eğlenmeye çalışın!

Tüm iyi yarışmaların kazanmanın nesnel bir tanımı vardır; ergo:

  • Tüm kurallara uyulması koşuluyla, en küçük sıkıştırılmış çıktı ( STDOUTbayt cinsinden) kazanır.
    • (Çıktınızı lütfen üzerinden bildirin ./cmprss | wc -c)
  • Beraberlik durumunda (özdeş çıktı boyutları), en çok oy alan topluluk kazanır.
  • İkinci bir beraberlik durumunda (özdeş topluluk oyları), tamamen öznel bir zarafet ve saf deha sınavına dayanan bir kazanan seçeceğim. ;-)

Nasıl gönderilir:

Lütfen bu şablonu kullanarak girişinizi biçimlendirin:

<language>, <compressed_size>
-----------------------------

<description>  (Detail is encouraged!)

    <CODE...
    ...>

<run instructions>

Okuyucuları ve göndericileri yorumlarla sohbet etmeye teşvik ederim - İnsanların codegolf.stack aracılığıyla öğrenmeleri ve daha iyi programcılar olmaları için gerçek bir fırsat olduğuna inanıyorum.

Kazanan:

Yakında tatildeyim: Önümüzdeki birkaç hafta içinde başvuruları izliyor olabilirim (ya da olmayabilirim) ve 19 Eylül'de mücadeleyi sona erdireceğim. Umarım bu, insanların düşünmesi ve sunması için - ve tekniklerin ve fikirlerin olumlu bir şekilde paylaşılması için iyi bir fırsat sunar.

Katılmaktan yeni bir şey öğrendiyseniz (okuyucu veya gönderici olarak) lütfen bir cesaret yorumu bırakın.


1
Bunu etiketlemelisiniz code-challenge.
kirbyfan64sos

1
Girdiyi işlev bağımsız değişkeni olarak almaya izin veriliyor mu? Örneğin JavaScript gibi dillerde bir çözüm olan AFAIK komut satırından çalıştırılamadı. Benim durumumda, tarayıcıda çalıştırmak çok daha kolay olurdu.
ETHproductions

1
Neden şablon? Buna bağlı bir yığın snippet'i mi oluşturacaksınız?
Peter Taylor

2
Kod boyutu sınırı yoksa, 0 bayt basan bir sıkıştırma programı ve Shakespeare'in tüm çalışmalarını yazdırmak için sabit kodlanmış bir açma programı yazmamı engelleyen nedir?
Lynn

4
Kodun teorik olarak @Mauris'in işaret ettiği sorunu çözen diğer girdilerle çalışması gerektiğini söyleyen bir kural eklenebilir .
kirbyfan64sos

Yanıtlar:


5

Perl 5, 3651284

Sadece basit bir kelime tabanlı sözlük şeması. Korpusun kelime sıklığını analiz eder ve bunu kelime başına bir veya iki bayt ek yükü kullanıp kullanmayacağını belirlemek için kullanır. \ 0 ve \ 1 baytları için iki özel sembol kullanır, çünkü bunlar kümede görünmezler. Kullanılabilecek başka semboller de vardır. Bu yapılmadı. Herhangi bir huffman kodlaması veya bu cazın hiçbirini yapmaz.

Sıkıştırma komut dosyası shakespeare.pl:

use strict;
use warnings;
use bytes;

my $text = join "", <>;
my @words = split/([^a-zA-Z0-9]+)/, $text;


my %charfreq;
for( my $i = 0; $i<length($text); ++$i ) {
    $charfreq{ substr($text, $i, 1) }++
}
for my $i ( 0..255 ) {
    my $c = chr($i);
    my $cnt = $charfreq{$c} // 0;
}



my %word_freq;
foreach my $word ( @words ) {
    $word_freq{ $word }++;
}


my $cnt = 0;
my ( @dict, %rdict );
foreach my $word ( sort { $word_freq{$b} <=> $word_freq{$a} || $b cmp $a } keys %word_freq ) {
    last if $word_freq{ $word } == 1; 


    my $repl_length = $cnt < 127 ? 2 : 3;
    if( length( $word ) > $repl_length ) {
        push @dict, $word;
        $rdict{ $word } = $cnt;
        $cnt++;
    }
}


foreach my $index ( 0..$
    print "$dict[$index]\0";
}
print "\1";


foreach my $word ( @words ) {
    my $index = $rdict{ $word };
    if ( defined $index && $index <= 127 ) {
        print "\0" . chr( $index );
    } elsif ( defined $index ) {
        my $byte1 = $index & 127;
        my $byte2 = $index >> 7;
        print "\1" . chr( $byte2 ) . chr( $byte1 );
    } else {
        print $word;
    }
}

Dekompresyon komut dosyası deshakespeare.pl:

use strict;
use warnings;
use bytes;

local $/;
my $compressed = <>;
my $text = $compressed;
$text =~ s/^.+?\x{1}//ms;
my $dictionary = $compressed;
$dictionary =~ s/\x{1}.*$//ms;


my $cnt = 0;
my @dict;
foreach my $word ( split "\0", $dictionary ) {

    push @dict, $word;
}


my @words = split /(\x{0}.|\x{1}..)/ms, $text;
foreach my $word ( @words ) {
    if( $word =~ /^\x{0}(.)/ms ) {
        print $dict[ ord( $1 ) ];
    } elsif( $word =~ /^\x{1}(.)(.)/ms ) {
        my $byte1 = ord( $1 );
        my $byte2 = ord( $2 );
        my $index = ( $byte1 << 7 ) + $byte2;
        print $dict[ $index ];
    } else {
        print $word;
    }
}

Kullanarak çalıştırın:

perl shakespeare.pl < pg100.txt >pg100.txt.compressed
perl deshakespeare.pl <pg100.txt.compressed >pg100.txt.restored
diff pg100.txt pg100.txt.restored
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.