Nén để tạo ấn tượng


8

Lấy cảm hứng từ cả thử thách "Unique is Cheap" của @Laikoni , trong đó điểm số dựa trên chính thử thách, cũng như câu trả lời JavaScript (ES6) của @ETHproductions cho thử thách "Nén Palindrom" , trong đó anh ta sử dụng một thử thách khá hay phương pháp nén cho cờ palindrom, chữ hoa / chữ thường và chữ cái.

Thử thách:

Bạn sẽ tạo hai chương trình / chức năng: chương trình / chức năng nén và chương trình / chức năng giải nén.

Nén chương trình / chức năng:

Với các nhân vật sử dụng trong mã nguồn của riêng bạn (cả mã nén và giải nén nguồn kết hợp) như chỉ đầu vào có thể, sử dụng bất kỳ loại phương pháp bit nén của sự lựa chọn và đầu ra của bạn kết quả 0s và 1s của bit-nén của đầu vào này .

Số lượng bit ( 0s và 1s) xuất ra phải càng ngắn càng tốt và số tiền này sẽ là số điểm của câu trả lời của bạn .

Ý tưởng là có sự cân bằng tốt giữa các loại ký tự khác nhau được sử dụng trong mã nguồn của riêng bạn, kích thước của các chương trình / chức năng của bạn và loại nén bit mà bạn đã sử dụng. Hoặc để trích dẫn @RobertFraser trong bình luận này :

Đây là một ví dụ tuyệt vời về các nguyên tắc cơ bản của kỹ thuật. Lấy một mô tả vấn đề, suy nghĩ về các cách khác nhau để giải quyết nó và tạo ra sự đánh đổi giữa các yêu cầu (nghĩa là có bao nhiêu bit để dành cho các phong cách khác nhau), v.v.

Quy tắc thử thách:

  • Chương trình / chức năng nén và giải nén phải cùng ngôn ngữ lập trình.
  • Bạn phải cung cấp cả chương trình / chức năng nén và giải nén, và số lượng 0s và 1s đầu ra chương trình nén của bạn cho cả hai chương trình / chức năng được kết hợp (được che giấu) vì đầu vào sẽ là điểm số của bạn.
  • Việc nén phải - rõ ràng - hoạt động đối với tất cả các ký tự được sử dụng trong mã nguồn của cả chương trình / chức năng nén và giải nén của bạn, theo bất kỳ thứ tự hoặc số tiền nào. (Nó có thể có hành vi không xác định cho bất kỳ ký tự nào không có trong mã nguồn của bạn.)
  • Kiểu đầu vào không nhất thiết phải là một chuỗi. Nó cũng có thể là một danh sách / mảng / luồng ký tự và nó có thể là đối số chương trình, STDIN, v.v. Cuộc gọi của bạn.
    Áp dụng tương tự cho đầu ra. Có thể được trả về từ một chức năng hoặc in ra STDOUT. Có thể là một chuỗi đơn, mảng số nguyên, v.v.
  • Chương trình nén của bạn phải xuất ít nhất một 0hoặc 1(vì vậy một catchương trình trống cho cả chương trình nén và giải nén là không thể).
  • Mã nguồn của bạn có thể không chỉ chứa 0s và 1s, ngoại trừ no-op (để ngăn các ngôn ngữ lập trình in mã nguồn của riêng chúng theo mặc định, trong đó cả hai chương trình nén và giải nén có thể là một 0hoặc 1một phần và không có op để ngăn chặn hành vi này với một bình luận không được sử dụng, xin lỗi các ngôn ngữ lập trình dựa trên nhị phân chỉ sử dụng 0s và 1s làm mã nguồn).
  • Mặc dù bạn sẽ phải hỗ trợ đầu vào từ 0 hoặc nhiều nhóm ký tự được sử dụng trong các chương trình / chức năng của mình, bạn không phải hỗ trợ đầu vào trống. Vì vậy, bạn có thể giả sử mỗi đầu vào sẽ có ít nhất 1 ký tự.
  • Một đầu vào có thể có thể lớn hơn kích thước nén và giải nén của bạn cộng lại.
  • Nếu vì bất kỳ lý do gì, phương pháp nén của bạn phụ thuộc vào thứ tự và có đầu ra ngắn hơn khi đầu vào của bạn DecompressionProgramCompressionProgramthay vì CompressionProgramDecompressionProgram, bạn được phép chọn thứ tự che giấu các chương trình / chức năng cho điểm số của mình.

Thí dụ:

Giả sử chương trình nén là ABCvà chương trình giải nén là 123aBc. Đối với bất kỳ đầu vào nào chứa 0 hoặc nhiều nhóm ký tự 123ABCab, nó có thể nén chính xác các ký tự đó thành 0s và 1s, và có thể giải nén các 0s và 1s này trở lại thành các ký tự chính xác. Một số ví dụ đầu vào hợp lệ cho hai chương trình này có thể là: ABC123aBc(tất nhiên); A; 1Ca; 22222b1121221b; Vân vân.

Quy tắc chung:

  • Các quy tắc chuẩn áp dụng cho câu trả lời của bạn, vì vậy bạn được phép sử dụng STDIN / STDOUT, các hàm / phương thức với các tham số thích hợp, các chương trình đầy đủ. Cuộc gọi của bạn.
  • Lỗ hổng mặc định bị cấm.
  • Nếu có thể, vui lòng thêm một liên kết với một bài kiểm tra cho mã của bạn.
  • Ngoài ra, xin vui lòng thêm một lời giải thích nếu cần thiết.

Ví dụ về câu trả lời:

Java 8, điểm số 1440 bit, 180 (87 + 93) byte

Đây là một triển khai rất tệ trong Java 8, trong đó mỗi ký tự được in đơn giản là Chuỗi nhị phân 8 bit.

Chức năng nén:

Đầu vào được cung cấp như java.util.stream.IntStream.

s->s.forEach(c->System.out.print("".format("%8s",Long.toString(c,2)).replace(' ','0')))

Hãy thử trực tuyến.

Chức năng giải nén:

Đầu vào được cung cấp như String.

s->{for(Integer i=0;i<s.length();System.out.printf("%c",i.parseInt(s.substring(i,i+=8),2)));}

Hãy thử trực tuyến.


Đây không phải là một bài kiểm tra quine, vì vậy tôi có thể đọc mã nguồn của mình không?
Weijun Zhou

@WeijunZhou Phụ thuộc vào những gì bạn sử dụng nó, nhưng tôi có thể cho phép nó trong hầu hết các trường hợp. Tôi đoán bạn muốn đọc mã nguồn của mình và sau đó ánh xạ dễ dàng các ký tự của nó bằng bảng tra cứu, hoặc một cái gì đó tương tự?
Kevin Cruijssen

Vâng, một cái gì đó tương tự là trong tâm trí của tôi.
Weijun Zhou

1
Tôi có thể đã bỏ lỡ điều gì đó, nhưng đây là một lỗ hổng có thể có trong các quy tắc: máy nén-> if input==compr_code+decompr_code then return 0 else return binary charcodes of input, bộ giải nén-> if input==0 then return compr_code+decompr_code else convert binary codes to characters and return them. Điểm cuối cùng: 1 (thấp nhất có thể). Các chương trình sẽ không tầm thường để viết, nhưng với một số thủ thuật từ các câu hỏi, chúng chắc chắn có thể thực hiện được.
Leo

@Leo Hmm, bạn thực sự đúng khi các quy tắc hiện tại cho phép câu trả lời như vậy (tất nhiên là vô tình). Tuy nhiên, không chắc chắn cách khắc phục nó .. Tôi có thể nói rằng bạn phải cung cấp ánh xạ bạn đã sử dụng cho từng ký tự riêng lẻ, phải tương ứng / giống nhau cho đầu vào bộ nén + giải nén cũng như mọi cấu hình ngẫu nhiên của các ký tự này. Nhưng trong trường hợp đó tôi có thể giới hạn các câu trả lời có thể, những người muốn nén các cặp ký tự, hoặc bất cứ điều gì họ đưa ra. Bất kỳ đề xuất nào về quy tắc để đóng lỗ hổng này, nhưng vẫn để lại sự linh hoạt cho sự sáng tạo? ..
Kevin Cruijssen

Câu trả lời:



2

Java (OpenJDK 9) , điểm 702 bit, 88 (42 + 46) byte

Máy nén, 42 byte

$->new java.math.BigInteger($).toString(2)

Hãy thử trực tuyến!

Bộ giải nén, 46 byte

$->new java.math.BigInteger($,2).toByteArray()

Hãy thử trực tuyến!


Xin lỗi, tôi đang chơi với chi phí byte thấp ( hum , đối với Java, ý tôi là vậy) chứ không phải nén cứng: S
Olivier Grégoire

Thậm chí còn không biết có thể đặt bất kỳ thứ gì Stringvào hàm BigIntegertạo .. Hình nó sẽ cung cấp NumberFormatException hoặc một cái gì đó .. Tôi đã biết về .toString(2). Tôi đoán câu trả lời tốt đẹp của tôi. ;)
Kevin Cruijssen

@KevinCruijssen Thật vậy, như hiện tại, nó giống như một ví dụ của bạn hơn bất cứ thứ gì khác. 703 bit có nghĩa là 88 byte. Tôi không thể nén bất cứ thứ gì dưới 88 byte cho đến nay, nhưng tôi vẫn đang cố gắng ;-)
Olivier Grégoire

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.