Viết một nén sử dụng cho các tập tin gzip


11

Nhiệm vụ của thử thách này như sau:

Viết chương trình đọc tệp có kích thước hợp lý (giả sử <16 MB) từ stdin hoặc bất kỳ nơi nào khác (tuy nhiên bạn thích, nhưng không được mã hóa cứng) và đặt đầu ra được nén vào thiết bị xuất chuẩn. Đầu ra phải là một tệp nén gzip hợp lệ và nếu tệp nén chạy qua gunzip, nó sẽ mang lại chính xác cùng một tệp như trước đây.

Quy tắc

  • Ngôn ngữ lập trình được sử dụng phải được biết trước khi cuộc thi này bắt đầu
  • Điểm của chương trình của bạn là số lượng ký tự của mã nguồn hoặc chương trình được lắp ráp (bất cứ điều gì ngắn hơn)
  • Bạn không được phép sử dụng bất kỳ loại thư viện nén hiện có nào.
  • Chúc vui vẻ!

2
Việc sử dụng các thư viện tích hợp có được phép không?
hallvabo

@hallvabo: Không. Quên điều này. Thx
FUZxxl

2
Có lẽ cách tốt nhất để làm điều này chỉ là đệm đầu vào với các dấu "khối sau không nén" ở đầu mỗi khối.
Anon.

gzip là ngôn ngữ lập trình. Không phải là một Turing hoàn thành một mặc dù.
Alexandru

1
Điều này khá giống với vấn đề Guns and Zips . Tại sao mọi người sẽ đăng câu trả lời của họ ở đây thay vì tại codegolf.com lại nằm ngoài tôi, trừ khi họ muốn giải quyết nó bằng ngôn ngữ không được codegolf.com hỗ trợ (ví dụ: GolfScript).
Chris Jester-Young

Câu trả lời:


10

C # (534 ký tự)

using System.IO;using B=System.Byte;class X{static void Main(string[]a){var f=File.ReadAllBytes(a[0]);int l=f.Length,i=0,j;var p=new uint[256];for(uint k=0,r=0;k<256;r=++k){for(j=0;j<8;j++)r=r>>1^(r&1)*0xedb88320;p[k]=r;}uint c=~(uint)0,n=c;using(var o=File.Open(a[0]+".gz",FileMode.Create)){o.Write(new B[]{31,139,8,0,0,0,0,0,4,11},0,10);for(;i<l;i++){o.Write(new B[]{(B)(i<l-1?0:1),1,0,254,255,f[i]},0,6);c=p[(c^f[i])&0xFF]^c>>8;}c^=n;o.Write(new[]{(B)c,(B)(c>>8),(B)(c>>16),(B)(c>>24),(B)l,(B)(l>>8),(B)(l>>16),(B)(l>>24)},0,8);}}}

Dễ đọc hơn nhiều:

using System.IO;
using B = System.Byte;
class X
{
    static void Main(string[] a)
    {
        // Read file contents
        var f = File.ReadAllBytes(a[0]);
        int l = f.Length, i = 0, j;

        // Initialise table for CRC hashsum
        var p = new uint[256];
        for (uint k = 0, r = 0; k < 256; r = ++k)
        {
            for (j = 0; j < 8; j++)
                r = r >> 1 ^ (r & 1) * 0xedb88320;
            p[k] = r;
        }

        uint c = ~(uint) 0, n = c;

        // Write the output file
        using (var o = File.Open(a[0] + ".gz", FileMode.Create))
        {
            // gzip header
            o.Write(new B[] { 31, 139, 8, 0, 0, 0, 0, 0, 4, 11 }, 0, 10);
            for (; i < l; i++)
            {
                // deflate block header plus one byte of payload
                o.Write(new B[] { (B) (i < l - 1 ? 0 : 1), 1, 0, 254, 255, f[i] }, 0, 6);
                // Compute CRC checksum
                c = p[(c ^ f[i]) & 0xFF] ^ c >> 8;
            }
            c ^= n;
            o.Write(new[] {
                // CRC checksum
                (B) c, (B) (c >> 8), (B) (c >> 16), (B) (c >> 24),
                // original file size
                (B) l, (B) (l >> 8), (B) (l >> 16), (B) (l >> 24)
            }, 0, 8);
        }
    }
}

Bình luận:

  • Dự kiến ​​đường dẫn đến tệp như là đối số dòng lệnh đầu tiên.

  • Tệp đầu ra là tệp đầu vào + .gz.

  • Tôi không sử dụng bất kỳ thư viện nào để thực hiện gzip, deflate hoặc CRC32. Tất cả đều ở đó.

  • Máy nén này có thể tăng kích thước tệp lên 6 lần nhưng ở định dạng gzip hợp lệ!

  • Đã thử nghiệm bằng GNU gunzip và WinRAR.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.