무손실 영어 텍스트 압축 문제 [닫기]


12

도전:

당신의 도전은 (당신이 그것을 받아들이도록 선택해야한다) 여기에 있는 5MB " William Shakespeare의 완전한 작품 "을 압축하고 압축 해제하는 것입니다 : http://www.gutenberg.org/cache/epub/100/pg100.txt

(MD5 : a810f89e9f8e213aebd06b9f8c5157d8)

규칙 :

  • 당신은 있어야 통해 입력 받아 STDIN통해 출력을 STDOUT...
  • ... 입력에 동일한 압축 해제 결과를 제공 해야합니다 .
    • (이것은 위와 동일한 MD5를 얻을 수 있어야한다는 것 입니다.)cat inpt.txt | ./cmprss | ./dcmpress | md5
    • (모든 것을 통해 STDERR버려집니다.)
  • 당신은 있어야합니다 총 소스 코드 미만 2,048 문자를 사용합니다.
    • (입니다 하지 코드 골프. 당신이 하지 소스 코드의 길이에 따라 득점되고. 이것은 이다 유한 물건을 유지하기 위해 단지 규칙이었다.)
    • (모든 소스 코드를 분리 한 경우 연결된 길이를 사용하십시오.)
  • 유사한 일반 텍스트 입력도 (이론적으로) 처리 할 수 있어야합니다 .
    • (예 : 제공된 셰익스피어 입력 출력 할 수 있는 메커니즘을 하드 코딩하는 것은 허용되지 않습니다.)
    • (압축되지 않은 결과가 다른 입력과 동일하다면 다른 문서의 압축 된 크기는 관련이 없습니다.)
  • 원하는 언어를 선택할 수 있습니다 .
    • (예 :를 사용하여 압축 awk및 압축 해제 java)
  • 두 개의 개별 프로그램을 작성하거나 원하는대로 "스위치"형식과 결합 할 수 있습니다 .
    • (압축 및 압축 해제 모드를 모두 호출하는 방법에 대한 명확한 데모가 있어야합니다)
  • 외부 명령을 사용할 수 없습니다 (예 :를 통해 exec()).
    • (쉘 언어를 사용하는 경우-죄송합니다. 내장 기능을 사용해야합니다. 공유 및 즐거움을 위해 "허용 할 수없는"답변을 게시해도 무방합니다. 그러나 판단되지는 않습니다! )
  • 데이터를 압축하기위한 목적으로 내장 또는 라이브러리 제공 함수를 사용할 수 없습니다 (예 gz: 등).
    • (이 문맥에서 인코딩을 압축하는 것은 압축으로 간주되지 않습니다. 여기에 일부 재량이 적용될 수 있습니다. 제출시 솔루션의 수용 가능성을 자유롭게 논의하십시오.)
  • 참가를 선택하면 즐거운 시간을 보내십시오!

모든 좋은 경쟁은 승리의 객관적인 정의를 가지고 있습니다. 에르고 :

  • 모든 규칙을 준수하면 가장 작은 압축 출력 ( STDOUT바이트)이 이깁니다.
    • (을 통해 출력을보고하십시오 ./cmprss | wc -c)
  • 추첨 (동일한 출력 크기)의 경우, 가장 많은 커뮤니티가 투표권을 얻습니다.
  • 두 번째 추첨 (동일한 커뮤니티 투표)의 경우, 나는 주관적인 우아함과 순수한 천재에 대한 주관적인 검토를 바탕으로 우승자를 선정 할 것입니다. ;-)

제출 방법 :

이 템플릿을 사용하여 항목을 형식화하십시오.

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

<description>  (Detail is encouraged!)

    <CODE...
    ...>

<run instructions>

독자와 제출자가 의견을 통해 대화하도록 권장합니다. 사람들이 codegolf.stack을 통해 더 나은 프로그래머가되고 배울 수있는 실질적인 기회가 있다고 생각합니다.

승리:

곧 휴가를 떠납니다. 다음 몇 주 동안의 제출물을 모니터링하거나 모니터링하지 않을 수 있으며 9 월 19 일에 마감 될 것입니다. 나는 이것이 사람들이 생각하고 제출할 수있는 좋은 기회를 제공하고 기술과 아이디어를 긍정적으로 공유하기를 희망합니다.

독자 또는 제출자로서 참여하여 새로운 것을 배운 경우 격려의 의견을 남겨주십시오.


1
이 태그를 지정해야합니다 code-challenge.
kirbyfan64sos

1
함수 인수로 입력을 받아들입니까? 예를 들어 JavaScript와 같은 언어의 솔루션은 명령 행 AFAIK에서 실행할 수 없습니다. 필자의 경우 브라우저에서 실행하는 것이 훨씬 쉽습니다.
ETHproductions

1
왜 템플릿입니까? 그것에 의존하는 스택 스 니펫을 작성 하시겠습니까?
피터 테일러

2
코드 크기 제한이없는 경우 0 바이트를 인쇄하는 압축 프로그램과 셰익스피어의 전체 작품을 인쇄하기 위해 하드 코딩 된 압축 해제 프로그램을 작성하지 못하게하는 이유는 무엇입니까?
Lynn

4
@Mauris가 지적한 문제를 해결하는 코드는 이론적 으로 다른 입력과 함께 작동 해야한다는 규칙을 추가 할 수 있습니다 .
kirbyfan64sos

답변:


5

펄 5, 3651284

간단한 단어 기반 사전 체계입니다. 말뭉치의 단어 빈도를 분석하고이를 사용하여 단어 당 1 바이트 또는 2 바이트의 오버 헤드를 사용할지 여부를 결정합니다. 코퍼스에 나타나지 않기 때문에 바이트 \ 0 및 \ 1에 대해 두 개의 특수 기호를 사용합니다. 사용할 수있는 다른 기호가 많이 있습니다. 이것은 이루어지지 않았습니다. 허프만 인코딩이나 그 재즈를 수행하지 않습니다.

압축 스크립트 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;
    }
}

압축 해제 스크립트 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;
    }
}

다음을 사용하여 실행하십시오.

perl shakespeare.pl < pg100.txt >pg100.txt.compressed
perl deshakespeare.pl <pg100.txt.compressed >pg100.txt.restored
diff pg100.txt pg100.txt.restored
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.