컨텍스트 프리 문법으로 데이터 압축


9

휴먼 텍스트 또는 소스 코드와 같은 일부 종류의 데이터를 직선 문법으로 압축 할 수 있습니다. 기본적으로 언어에는 압축되지 않은 데이터라는 단어가 정확히 하나 인 문법이 작성됩니다. 이 작업에서는 이러한 데이터 압축 방법을 구현하는 프로그램을 작성해야합니다.

입력

입력은 65535 바이트 이하의 문자열입니다. 입력이 정규식과 일치 함을 보증합니다 [!-~]+(즉, 공백을 제외하고 인쇄 가능한 ASCII 문자 하나 이상).

입력 예는 다음과 같습니다.

abcabcbcbcabcacacabcabab

산출

출력은 정확히 한 단어 (입력)를 설명하는 문법을 구성하는 규칙 집합입니다. 각 비 터미널은 9보다 큰 10 진수로 표시됩니다. 시작 기호는 기호 번호 10입니다. 입력 예에 해당하는 출력 예는 다음과 같습니다. 구문은 아래에 자세히 설명되어 있습니다.

10=11 11 12 12 11 13 13 11 14 14
11=a 12
12=b c
13=a c
14=a b

각 규칙은 <nonterminal>=<symbol> <symbol> ...오른쪽에 임의의 공백으로 구분 된 수의 기호 가있는 형식 입니다. 다음 제한 사항을 준수하고 정확하게 입력 문자열을 도출하는 각 출력이 유효합니다.

제한 사항

사람들이 이상한 일을하는 것을 막기 위해 여러 가지 제한이 있습니다.

  • 각 비 터미널은 규칙의 오른쪽에 두 번 이상 나타나야합니다. 예를 들어, abcabc규칙 12가 한 번만 나타나기 때문에 입력에 대한 다음 문법 은 유효하지 않습니다.

    10=12
    11=a b c
    12=11 11
    
  • 두 개의 인접한 심볼 시퀀스는 겹치는 경우를 제외하고 모든 규칙의 모든 오른쪽에 두 번 이상 나타날 수 없습니다. 예를 들어, 입력에 대한 다음 문법 abcabcbc은 시퀀스 bc가 두 번 나타나 므로 유효하지 않습니다.

    10=11 11 b c
    11=a b c
    

    유효한 문법은 다음과 같습니다.

    10=11 11 12
    11=a 12
    12=b c
    
  • 65535 바이트를 초과하지 않는 유효한 각 입력마다 1 분 이내에 프로그램을 종료해야합니다.

  • 평소와 같이 솔루션을 사소하게 만들거나 많은 부분을 구현하는 언어 기능이나 라이브러리 기능을 사용할 수 없습니다.

샘플 입력

다음 C 프로그램으로 샘플 입력을 생성하십시오.

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

int main(int argc, char **argv) {
  unsigned int i,j = 0,k;

  if (argc != 3
     || 2 != sscanf(argv[1],"%u",&i)
      + sscanf(argv[2],"%u",&k)) {
    fprintf(stderr,"Usage: %s seed length\n",argv[0]);
    return EXIT_FAILURE;
  }

  srand(i);

  while(j < k) {
    i = rand() & 0x7f;
    if (i > 34 && i != 127) j++, putchar(i);
  }

  return EXIT_SUCCESS;
}

위 프로그램에서 생성 된 샘플 입력은 일반적으로 압축 결과가 좋지 않습니다. 휴먼 텍스트 또는 소스 코드를 예제 입력으로 사용하십시오.

우승 기준

이것은 코드 골프입니다. 가장 짧은 소스 코드를 가진 프로그램이 승리합니다. 추가 크레딧을 얻으려면 출력의 입력을 재구성하는 프로그램을 작성하십시오.


ㅋ. kolmogorov- 복잡성 질문을 위해 Java로 구현 된 (골프는 아님) 몇 가지 버전이 이미 있습니다 ...
Peter Taylor

@PeterTaylor 정확히 어떤 질문이 있습니까?
FUZxxl

게시 할 가치가있는 짧은 답변을 반드시 찾지는 못하지만 (저는 문법 생성 전략과 문법 엔진을 천천히 추가하고 있습니다), 그 프로젝트의 핵심 스크립트는 codegolf.stackexchange.com/questions/1682 , codegolf 에서 시도합니다 .stackexchange.com / questions / 6043 , codegolf.stackexchange.com/questions/4191 , codegolf.stackexchange.com/questions/4356 및 기타 질문의 일부 구성 요소.
피터 테일러

답변:


3

GolfScript, 111 개 108 문자

1/{.}{:^1<{^1$/,2>.{;,)^<.0?)!}*}do-1<.,1>{^1$/[10):10]*0+\+}{;^}if(\}while][0]%.,,]zip{))9+`"="+\~" "*+}%n*

이것은 GolfScript를 사용하는 매우 서투른 접근법입니다. 두 번째 버전은 초기 버전보다 훨씬 우수합니다. 의도 된 코드보다 훨씬 길지만 내 구현에 중첩 루프가있어 인터프리터에 문제가 발생했습니다.

예 :

> abcba
10=a b c b a

> abcabcbc
10=11 11 12
11=a 12
12=b c

> abcabcbcbcabcacacabcabab
10=11 12 12 13 14 14 c 11 15
11=15 13
12=c b
13=14 b
14=c a
15=a b

1

취소됨-알고리즘이 모든 경우를 처리 할 수 ​​없습니다. C, 422 (출력에서 딥을 제거하고 문자를 삭제하도록 수정 됨)

초기 구현은 골프를 시작합니다.

규칙은 실제로이 무차별 대입 방식을 압축 할 필요가 없기 때문에 ...

10 초 내에 65535 길이 처리 가능

n,m[99999];
c,r[99999][2];

g,i,s,t;

main(){
    for(;(m[n]=getchar())>32;n++);

    while(!g){ // loop until no further changes
        g=1;
        for(s=0;s<n-1;s++) {
            for(t=s+2;t<n-1;t++)if(m[s]==m[t]&&m[s+1]==m[t+1]){
                // create rule
                r[c][0]=m[s];
                r[c++][1]=m[s+1];
                g=0;
                // substitute
                for(i=t=s;i<n;i++){
                    if(m[i]==r[c-1][0]&&m[i+1]==r[c-1][1]){
                        m[t++]=-c;
                        i++;
                    }else
                        m[t++]=m[i];
                }
                n=t;
            }
        }
    }

    for(s=-1;s<c;s++){
        printf("%d=",s+11);
        for(t=0;t<(s<0?n:2);t++){
            i=(s<0?m:r[s])[t];
            i<0?printf("%d ",10-i):printf("%c ",i);
        }
        printf("\n");
    }

}

샘플 실행 :

echo abcabcbcbcabcacacabcabab | a.out
10=11 12 13 13 12 14 14 12 12 11 
11=a b 
12=c 11 
13=c b 
14=c a


사양에 따라 코드가 작동하지 않습니다. 규칙을 위반하는 출력을 생성 하여 두 문자 시퀀스가 ​​두 번 나타날 수 없습니다 . 입력 abcdabcd를 고려하십시오. 또한 코드는 분명히 입력 스트림에서 마지막 바이트를 제거합니다. 두 가지 효과를 모두 관찰하는 예제를 보려면 여기를보십시오. ideone.com/3Xvtyv
FUZxxl

또한 샘플 출력이 잘못되었습니다.
FUZxxl

네 말이 맞아-내가 실패했다-내가 직장에서 돌아올 때 그것을 볼 것이다 : P
baby-rabbit

그것은 나를 위해 입력에서 마지막 바이트를 제거하지 않습니다-그리고 나의 샘플 출력이 맞습니다 (나를 위해). "spot the bug"을 연주합시다!
baby-rabbit

게시 한 샘플 출력은 다음과 같습니다. 확장 된 형태의 규칙 10은 규칙 "14"로 끝나고 "ca"로 끝납니다. 마지막 c는 실제로 끝 전 5 자리입니다.
FUZxxl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.