Bağlamdan bağımsız gramerlerle verileri sıkıştırın


9

İnsan metni veya kaynak kodu gibi bazı veri türlerini düz çizgi dilbilgisi ile sıkıştırmak mümkündür. Temel olarak, dili tam olarak bir sözcük olan sıkıştırılmamış veriler olan bir dilbilgisi oluşturursunuz. Bu görevde, bu veri sıkıştırma yöntemini uygulayan bir program yazmanız gerekir.

Giriş

Giriş, 65535 bayt uzunluğundan daha uzun olmayan bir dizedir. Girişin normal ifadeyle eşleşmesi garanti edilir [!-~]+(örn. Boşluk hariç en az bir yazdırılabilir ASCII karakteri).

Örnek bir giriş

abcabcbcbcabcacacabcabab

Çıktı

Çıktı, tam olarak bir kelimeyi (girdi) tanımlayan bir dilbilgisi oluşturan bir dizi kuraldır. Her terminal dışı 9'dan büyük bir ondalık sayı ile gösterilir. Başlangıç ​​sembolü on numaralı semboldür. Örnek girişe karşılık gelen bir örnek çıktı aşağıda verilmiştir; sözdizimi aşağıda daha ayrıntılı olarak açıklanmaktadır:

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

Her kuralın <nonterminal>=<symbol> <symbol> ...sağ tarafında isteğe bağlı boşlukla ayrılmış sayıda sembol bulunan bir form bulunur. Aşağıdaki kısıtlamalara uyan ve tam olarak girdi dizesini türeyen her çıktı geçerlidir.

Kısıtlamalar

İnsanların garip şeyler yapmasını engellemek için bir takım kısıtlamalar vardır:

  • Her terminal dışı bir kuralın sağ tarafında en az iki kez görünmelidir. Örneğin, abcabckural 12 yalnızca bir kez göründüğünden , giriş için aşağıdaki dilbilgisi geçersizdir:

    10=12
    11=a b c
    12=11 11
    
  • Üst üste gelen iki sembol dizisi, üst üste binmeleri dışında, tüm kuralların sağ tarafında birden fazla görünemez. Örneğin abcabcbc, dizi bciki kez göründüğü için giriş için aşağıdaki dilbilgisi geçersizdir :

    10=11 11 b c
    11=a b c
    

    Geçerli bir dilbilgisi:

    10=11 11 12
    11=a 12
    12=b c
    
  • 65535 bayttan uzun olmayan her geçerli giriş için programınızın bir dakikadan daha kısa sürede sonlanması gerekir.

  • Her zaman olduğu gibi, dilinizin herhangi bir özelliğini veya çözümü önemsiz hale getiren veya büyük bir kısmını uygulayan herhangi bir kütüphane işlevini kullanamazsınız.

Örnek giriş

Aşağıdaki C programıyla örnek girişi oluşturun.

#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;
}

Yukarıdaki program tarafından üretilen örnek girişi genellikle iyi sıkıştırma sonuçları ile sonuçlanmaz. Örnek metin olarak insan metni veya kaynak kodu kullanmayı düşünün.

Kazanma kriterleri

Bu kod golf; en kısa kaynak kodlu program kazanır. Ekstra kredi için, çıktıdan girişi yeniden yapılandıran bir program yazın.


Ha ha. Zaten kolmogorov-karmaşıklık soruları için Java uygulanan (ama golf değil) birkaç sürümleri var ...
Peter Taylor

@PeterTaylor Tam olarak hangi sorular?
FUZxxl

Mutlaka yayınlanmaya değecek kadar kısa bir cevap bulamaz (yavaş yavaş dilbilgisi üreten stratejiler ve dilbilgisi motorları ekliyorum), ancak bu projedeki temel komut dosyası onları codegolf.stackexchange.com/questions/1682 , codegolf üzerinde deniyor .stackexchange.com / sorular / 6043 , codegolf.stackexchange.com/questions/4191 , codegolf.stackexchange.com/questions/4356 ve diğer soruların birkaç bileşeni.
Peter Taylor

Yanıtlar:


3

GolfScript, 111 108 karakter

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

Bu, GolfScript kullanan oldukça beceriksiz bir yaklaşımdır. İkinci sürüm, ilk sürümden çok daha iyi performans gösterir. Amaçlanan koddan çok daha uzun ama benim uygulama do-döngüler iç içe geçmişti ve bu yorumlayıcı ile sorunlara neden oldu.

Örnekler:

> 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

Geri çekildi - algoritma tüm durumları işleyemiyor. C, 422 (çıktıdaki çiftleri kaldırmak ve karakteri düşürmek için düzeltildi)

İlk uygulama, golf oynamaya başlayacaktır.

Kurallar, bu kaba kuvveti saf bir şekilde sıkıştırmasını gerektirmediği için saf yaklaşım yapacak ...

65535 uzunluğu 10 saniye içinde işleyebilir

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");
    }

}

Örnek çalışma:

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


Kodunuz spesifikasyona göre çalışmıyor. İki karakter dizisinin iki kez görünemeyeceği kuralı ihlal eden çıktılar üretir ; abcdabcd girişini göz önünde bulundurun. Ayrıca, kodunuz son baytı giriş akışından kaldırır. Her iki efekti gözlemlemek için bir örnek için buraya bakın: ideone.com/3Xvtyv
FUZxxl

Ayrıca, örnek çıktınız yanlış görünüyor.
FUZxxl

Haklısın - Başarısız oldum - İşten döndüğümde bakacağım: P
baby-rabbit

Benim için girişten son baytı kaldırmıyor - ve benim örnek çıktı (benim için) doğru .. Hadi "hata tespit" oynayalım!
bebek-tavşan

Kesinlikle gönderdiğiniz örnek çıktı. Kural 10'un genişletilmiş formu kural 14 ile biter ve bu da "ca" ile biter. Son c aslında sondan önce 5 pozisyon.
FUZxxl
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.