Bộ mã hóa ASCII động!


16

Giới thiệu

Một số nhân vật ASCII ngày nay rất đắt đỏ ...

Để tiết kiệm tiền, bạn đã quyết định viết một chương trình mã hóa các ký tự đắt tiền bằng cách sử dụng các ký tự rẻ tiền.

Tuy nhiên, giá nhân vật thay đổi thường xuyên và bạn không muốn sửa đổi chương trình của mình mỗi khi bạn cần mã hóa hoặc giải mã một ký tự khác! Bạn sẽ cần một giải pháp năng động hơn.

Thử thách

Nhiệm vụ của bạn là viết hai chương trình: bộ mã hóabộ giải mã .

Bộ mã hóa nên chấp nhận một danh sách năm ký tự rẻ tiền và một ký tự đắt tiền.

Nó sẽ xuất ra một chuỗi duy nhất được tạo thành từ các ký tự rẻ tiền, mã hóa ký tự đắt tiền.

Chuỗi này có thể không dài hơn 4 ký tự , để không tốn kém. Tuy nhiên, nó không phải sử dụng tất cả các ký tự rẻ tiền trong mã hóa và mã hóa có thể có độ dài khác nhau.


Bộ giải mã phải chấp nhận chuỗi được bộ mã hóa xuất ra và xuất ký tự đắt tiền.

Bộ giải mã phải chấp nhận không có đầu vào nào ngoài chuỗi được mã hóa. Nó phải hoạt động, không thay đổi, từ đầu ra của bộ mã hóa cho bất kỳ kết hợp (hợp lệ) nào của đầu vào. Nói cách khác, chương trình giải mã của bạn không biết nhân vật nào đắt tiền hay rẻ tiền.

Chấm điểm

Mã kết hợp ngắn nhất sẽ thắng!

Ghi chú

  • Tất cả các ký tự sẽ là chữ hoa [A-Z], chữ thường [a-z]hoặc số [0-9].

  • Danh sách các ký tự rẻ tiền sẽ không chứa các bản sao. Không có nhân vật sẽ vừa rẻ tiền và đắt tiền.

  • Bộ mã hóa và giải mã không phải được viết bằng cùng một ngôn ngữ, nhưng chúng có thể. Bạn có thể viết một chương trình hoặc một chức năng.

  • Đầu vào và đầu ra có thể ở bất kỳ định dạng hợp lý nào cho ngôn ngữ của bạn.

  • Hai chương trình có thể không chia sẻ bất kỳ biến hoặc dữ liệu.

Tóm lược

  • Đầu vào của một số ký tự rẻ tiền và một ký tự đắt tiền được trao cho bộ mã hóa.

  • Bộ mã hóa xuất ra một chuỗi các ký tự rẻ tiền, mã hóa ký tự đắt tiền.

  • Bộ giải mã được đưa ra đầu ra của bộ mã hóa và xuất ra ký tự đắt tiền.

Ví dụ

Đầu vào:     a, b, c, d, e     f

Khả năng mã hóa:     a     eeee     caec

Bộ giải mã:     f


Đầu vào:     a, b, c, d, e     h

Khả năng mã hóa:     bc     cea     eeaa

Bộ giải mã:     h


Đầu vào:     q, P, G, 7, C     f

Khả năng mã hóa:     777     P7     PPCG

Bộ giải mã:     f


Đây thực sự chỉ có thể là tôi, và tôi xin lỗi vì câu hỏi này nếu có, nhưng chính xác thì bạn phải mã hóa tin nhắn của mình bằng các ký tự rẻ tiền như thế nào? Bổ sung mã ASCII cho 5 ký tự rẻ tiền? Trên thực tế, câu hỏi này chỉ có cơ sở nếu bộ giải mã của bạn phải giải mã cho tất cả các khả năng mã hóa được tạo.
cole

Để rõ ràng: Khả năng của Bộ mã hóa chỉ là ví dụ và chúng ta có thể mã hóa từng ký tự theo ý muốn, đúng không?
Dennis

@Dennis Vâng, đó chỉ là những ví dụ.
jrich

@Cole Không cần đưa ra một thuật toán thực tế , vì đó là thách thức chính ở đây, tôi tin rằng điều đó là có thể. Theo A239914 , chỉ có 62 chữ cái đắt tiền có thể được mã hóa và với 4 ký tự ascii này có thể được mã hóa lên tới 92 . (nhờ rất lớn để bình luận sandbox PhiNotPi cho cái này - Tôi không tính toán chính xác có bao nhiêu có thể được mã hóa)
jrich

@Und xác định chức năng Bây giờ tôi nhận ra những gì bạn dự định: Câu hỏi của Dennis đã trả lời những gì tôi đã nhầm lẫn.
cole

Câu trả lời:


5

Bình thường, 46 byte

Bộ mã hóa, 22 byte

@smfql{Td^<Szd4S4-Cw48

Bộ giải mã, 24 byte

C+48xsmfql{Td^<sS{zd4S4z

Wow, điều đó hoàn toàn phù hợp. 75 kết hợp char khác nhau và phạm vi char 75.
Jakube

Tôi nghĩ bạn có thể thay thế S4bằng Tvà lưu từng byte một trong cả hai chương trình.
Jakube

7

CJam, 55 50 48 47 byte

Bộ mã hóa, 24 22 21 byte

l$:L4m*{$L|L=},rc'0-=

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

Bộ giải mã, 31 28 27 26 byte

4_m*{$4,|4,=},l_$_|f#a#'0+

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


Có một bảng cú pháp CJam ngoài đó bạn sử dụng? Cái trên sourceforge và tờ cheat pdf khác không chứa tất cả các ký tự bạn sử dụng như'
Sáng

'không phải là một nhà điều hành. Bạn có thể tìm thấy nó trên trang cú pháp .
Dennis

4

chim ưng, 163 + 165 = 328

Đã thử nghiệm với gawk 4.1.1, nhưng cũng nên hoạt động trong các phiên bản gawk cũ hơn. Cần phải sửa đổi một chút (kéo dài) để làm việc với mawk.

bộ mã hóa (163):

{for(gsub(", ",_);sprintf("%c",++r)!=$NF;asort(a))split($1,a,_);r-=r>64?53:46;for(k=4^5;r-=_~i;j=_)for(i=++k;gsub(++j,_,i);)split(k,b,_);for(j in b)printf a[b[j]]}

bộ giải mã (165):

{split($1,a,_);for(i in a)d[a[i]]=a[i];asort(d);for(k=4^5;c!~$1;x+=_~i){i=++k;for(c=j=_;gsub(++j,_,i);split(k,b,_));for(g in b)c=c d[b[g]]}printf"%c",x+(x>10?54:47)}

Vâng, nó hoạt động, nhưng tôi biết rằng đây có thể không phải là cách tiếp cận tốt nhất cho việc này. Tôi không biết bức thư rẻ tiền thứ năm dùng để làm gì, vì tôi chỉ sử dụng bốn.

Đây chỉ là cho sử dụng duy nhất. Nếu bạn muốn nhập mã thứ hai, bạn phải khởi động lại chúng. Các khoảng trắng sau dấu phẩy được yêu cầu trong đầu vào để mã hóa.

Những gì tôi nghĩ về

Câu hỏi đầu tiên của tôi là "Bộ giải mã có thể nhận được gì từ 4 ký tự này?" (Tôi sẽ gọi chúng là a, b, c và d) và ý tưởng ban đầu của tôi là lấy 6 bit Thông tin từ các mối quan hệ sau:

a>b
a>c
a>d
b>c
b>d
c>d

Wow, 6 bit, thật hoàn hảo! Tôi nghĩ rằng đó là thiên tài, nhưng thử nghiệm cho thấy điều này sẽ không hoạt động. Chỉ có 24 kết hợp có thể. Chỉ trích.

Bước tiếp theo là cố gắng đếm, dựa trên những gì tôi đã biết. Vì vậy, chữ cái đầu tiên xuất hiện trong chuỗi sẽ trở thành 0, sau đó chữ cái thứ hai được giới thiệu trong chuỗi sẽ trở thành 1 và cứ thế. Nhưng nó sẽ không mang lại cho tôi tất cả các cách kết hợp 62 cần thiết.

0000
0001
0010
0011
0012
0100
0101
0102
0110
0111
0112
0120
0121
0122
0123

Nhưng dù sao tôi cũng thích ý tưởng đó.

Chà, sau đó tôi nhận ra rằng tôi có thể kết hợp cả hai, bởi vì các nhân vật trong đầu vào đã có quan hệ và tôi sẽ không phải đợi cho đến khi chúng được giới thiệu để cho chúng một giá trị.

Làm thế nào nó hoạt động

Lưu ý: Đây không còn chính xác là cách các phiên bản golf hoạt động, nhưng nguyên tắc vẫn giữ nguyên.

Đối với bộ giải mã:

Một mảng được xây dựng, có chỉ mục chứa tất cả bốn số có chữ số lớn nhất không lớn hơn số chữ số riêng biệt trong số đó. Có 75 số bốn chữ số khác nhau đáp ứng điều kiện đó. Tôi vũ phu ép buộc họ, bởi vì cho đến nay tôi không thể tìm ra cách nào để xây dựng chúng, và tôi không chắc điều này sẽ ngắn hơn để làm trong awk. Trong khi tôi tìm thấy chúng, tôi gán cho chúng các ký tự đắt tiền theo thứ tự asciibory.

Sau đó, tôi thay thế mọi ký tự từ chuỗi đầu vào bằng một chữ số. Nhỏ nhất (ví dụ: 'B' nhỏ hơn 'a') trở thành 1, nhỏ nhất thứ hai trở thành 2, và lên đến 4. Tất nhiên, nó phụ thuộc vào số lượng ký tự khác nhau trong đầu vào, chữ số cao nhất trong chuỗi kết quả sẽ là.

Sau đó, tôi chỉ cần in phần tử mảng, có chuỗi đó là một chỉ mục.

Bộ mã hóa hoạt động tương ứng.

Cách sử dụng

Sao chép mã trực tiếp trong lệnh awk bash line hoặc tạo hai tệp "encode.awk" và "decode.awk" và dán mã tương ứng. Hoặc thậm chí tốt hơn là sử dụng mã sau, tự động thoát ra sau khi giải mã hoặc có thể được sử dụng nhiều lần bằng cách loại bỏ lệnh thoát ở cuối.

mã hóa.awk

{
    if(!x) # only do first time
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:0)++a[p];
            length(a)>=m&&i!~0?c[(x>9?55:48)+x++]=i:_
        }
    r=u=_; # clear reused variables 
    for(gsub(",",FS);sprintf("%c",++r)!=$NF;); # more flexible concerning
    --NF;                                      # spaces in input
    split($0,b);
    asort(b);
    split(c[r],a,_);
    for(j in a)u=u b[a[j]]; # prettier printing than golfed version
    print u
    exit # <=== remove to encode input file
}

giải mã.awk

{
    if(!x) # only do first time 
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:_)++a[p];
            length(a)>=m&&i!~0?c[i]=sprintf("%c",(x>9?55:48)+x++):_
        }
    delete t; delete d; o=_; # clear reused variables 
    split($1,a,_);
    for(i in a)t[a[i]]=1;
    for(i in t)d[++y]=i;
    asort(d);
    for(i in a)for(j in d)if(d[j]~a[i])o=o j;
    print c[o]
    exit # <=== remove to encode input file
}

Dưới đây là một ví dụ sử dụng:

me@home:~/$ awk -f encode.awk
w, 0, R, 1, d X
10R1
me@home:~/$ awk -f decode.awk
10R1
X

Hãy nhớ rằng không gian sau mỗi dấu phẩy là bắt buộc, nếu bạn sử dụng các phiên bản golf.

Nếu bạn muốn, bạn có thể sử dụng tập lệnh ngắn và bẩn này để tạo một số dữ liệu mẫu

BEGIN{
    for(srand();i++<1000;)
    {
        erg="";
        for(j=0;j++<5;)
        {
            while(erg~(a[j]=substr(c="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",rand()*62+1,1)));
            erg=erg a[j]
        }
        print a[1]", "a[2]", "a[3]", "a[4]", "a[5](rand()>.5?" ":rand()>.5?"  ":"   ")substr(c,rand()*62+1,1)
    }
}

và làm một cái gì đó buồn cười như

me@home:~/$ awk -f gen.awk|awk -f encode.awk|awk -f decode.awk|sort -u|wc -l
62

Tôi đã xem điều này nhiều hơn như một câu đố lập trình. Tôi nghĩ rằng có một chút buồn, rằng hầu hết mọi thứ ở đây đều được đánh gôn, bởi vì bạn có thể học được nhiều hơn từ mã tài liệu tốt, có thể đọc được, nhưng đó chỉ là ý kiến ​​của tôi. Và tôi đã chơi nó như yêu cầu;)


Làm thế nào để kiểm tra nó? xin vui lòng chia sẻ một số ví dụ.
Shravan Yadav

+1 cho lời giải thích tuyệt vời! Có vẻ có nhiều cách khác nhau để tiếp cận vấn đề này :)
jrich

1
Điều này rất giống với quá trình suy nghĩ của tôi ngoại trừ tôi đã không nhận ra vũ phu - buộc các kết hợp yếu duy nhất (trong đó bạn mô tả chữ số lớn nhất không lớn hơn số lượng chữ số) là một cách tiếp cận khả thi. Kudos để theo dõi thông qua.
Patrick Roberts
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.