Nén độc quyền


17

Đưa ra một chuỗi biểu thị trạng thái hiện tại của trò chơi Monopoly khi bắt đầu lượt chơi của người chơi, nén tất cả dữ liệu cần thiết vào đầu ra nhỏ nhất. Câu trả lời sẽ được đánh giá bởi kích thước đầu rakích thước nguồn .

Lưu ý: Có nhiều biến thể khu vực, nhưng tất cả các tham chiếu trong bài đăng này đến tên thuộc tính, v.v., đều dựa trên bảng này .


Đầu vào:

Đầu vào sẽ được cung cấp dưới dạng một ;chuỗi riêng biệt. Chuỗi này được trao cho chương trình theo bất kỳ cách nào là thông lệ trong ngôn ngữ bạn đã chọn, cho dù đó là stdin, đối số, v.v.

Đầu vào không được định dạng trông như thế này:

numPlayers                     (1 to 8)
whose turn                     (0 to numPlayers-1)
for each player:
    bankrupt?                  (true/false)
    money                      (0 to 2^16-1)
    get-out-of-jail-free cards (0 to 2)
    position                   (0 to 39) 
    jail turns                 (-1 to 2)
for 28 properties:
    owner                      (-1 to numPlayers-1)
    mortgaged?                 (true/false)
    improvement level          (0 to 5)
for 16 chance cards in deck:
    card index                 (-1 to 15)
for 16 community chest cards in deck:
    card index                 (-1 to 15)

Một ví dụ được định dạng đầu vào là đây:

3;1;false;1546;0;14;-1;false;7692;1;10;1;true;1;false;1;1;false;0;0;true;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;3;12;7;4;5;2;13;11;15;6;8;9;10;1;14;-1;

Lấy từng chút một:

3;1;

Có 3 người chơi và đến lượt 1 người chơi (không có chỉ số, vì vậy người chơi thứ hai )

Người chơi

false;1546;0;14;-1;
false;7692;1;10;1;
true;

Người chơi đầu tiên:

  • không phá sản
  • có sẵn $ 1546 tiền mặt
  • sở hữu 0 thẻ không cần ra tù
  • ở vị trí 14 (Virginia Ave)
  • không phải ở tù

Người chơi thứ hai đang ở trong tù, và đã được một lượt. Tôi không chắc tại sao , vì anh ta có thẻ GOoJF, nhưng anh ta ở đó.

Người chơi thứ ba bị phá sản, và nhiều thông tin không được yêu cầu cũng không được cung cấp.

Tính chất

1;false;1;
1;false;0;
0;true;0;
-1;false;0;
-1;false;0;
-1;false;0;
...

Các thuộc tính được liệt kê theo thứ tự xung quanh bảng, bắt đầu từ Địa Trung Hải và kết thúc tại Boardwalk. Các thuộc tính không thể sở hữu không được bao gồm trong danh sách này, do đó sẽ có tổng cộng 28. Mức độ cải thiện 0có nghĩa là không được chứng minh. Cấp 1là một ngôi nhà, lên đến cấp 5cho một khách sạn. Một -1chủ sở hữu có nghĩa là nó không thuộc sở hữu của bất kỳ người chơi.

Theo các quy tắc tiêu chuẩn, một tài sản được thế chấp phải được sở hữu và không được cải thiện. Một tài sản được cải thiện phải được sở hữu và không được thế chấp.

Ngoài ra, để cải thiện một thuộc tính, người chơi phải sở hữu toàn bộ khối màu. Đối với mục đích của trò chơi này, chúng tôi không quan tâm nếu các thuộc tính đang được cải thiện "đồng đều".

Lưu ý rằng các vị trí này không giống với các vị trí người chơi được đưa ra ở trên. Chẳng hạn, một người chơi ở 5vị trí này sẽ ở Reading Railroad, đây là tài sản thứ ba trong danh sách (vì Go, Community Chest và Thuế thu nhập không thể được sở hữu). Vị trí người chơi chạy từ 0(Đi) theo chiều kim đồng hồ đến 39(Boardwalk).

thẻ

0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;
3;12;7;4;5;2;13;11;15;6;8;9;10;1;14;-1;

Mỗi bộ bài Cơ hội và Rương cộng đồng có 16tổng số thẻ. Các con số được trình bày khi chúng xuất hiện trong bộ bài đang xáo trộn. Trong ví dụ này, thẻ đầu tiên được rút ra khỏi bộ bài Chance sẽ là thẻ 0, tiếp theo là thẻ 1(bất kỳ ai xáo trộn bộ bài đó đều hút). Thẻ đầu tiên kéo từ Cộng đồng ngực là thẻ 3, sau đó 12.

Đừng lo lắng về ý nghĩa của mỗi thẻ (văn bản thẻ), ngoại trừ thẻ 0. Đó là thẻ Get Out of Jail Free cho bộ bài đó. Nếu một người chơi sở hữu nó, nó sẽ ở cuối danh sách, được đại diện là -1.


Đầu ra:

Bạn phải xuất (ra bàn điều khiển, thiết bị xuất chuẩn hoặc tệp) một đại diện cho trạng thái trò chơi. Điều này phải bao gồm tất cả các thông tin cần thiết để đại diện cho trò chơi. Ví dụ: bạn có thể bỏ qua (hoặc viết tắt) các thuộc tính chưa được đặt tên, vì chúng không thể được cải thiện hoặc thế chấp. Đầu vào không thể bỏ qua chúng vì đây là danh sách chưa được lập.

Nén phải được thực hiện theo cách mà bạn có thể tính kích thước đầu ra trong trường hợp xấu nhất. Điều này có thể loại bỏ các thuật toán nén nhất định (trừ khi bạn có thể chứng minh trường hợp xấu nhất và đưa ra ví dụ về trường hợp xấu nhất).

Trừ khi mã nguồn của bạn dài dòng một cách vô lý , hãy đưa ra lời giải thích về cách trò chơi được thể hiện. Câu trả lời không có gì ngoài một chương trình chơi gôn và đầu ra nén không được khuyến khích. Ví dụ: nếu bạn đang bỏ qua các giá trị nhất định, hãy giải thích làm thế nào có thể lấy được chúng từ đầu ra.


Ghi điểm / Quy tắc:

Ghi điểm dựa trên cả kích thước nén trong trường hợp xấu nhất theo bit và kích thước mã nguồn theo byte :

score = (outputBits * 2) + encoderSourceBytes

Một câu trả lời đầy đủ phải bao gồm:

  • Ví dụ đầu ra
  • Nguồn mã hóa
  • Nguồn giải mã (không được tính vào điểm số)

Tất cả các bộ mã hóa phải là chương trình hoàn chỉnh và các lỗ hổng tiêu chuẩn bị cấm. Sử dụng các thư viện nén tích hợp hoặc bên ngoài cũng bị cấm.

Người chiến thắng là câu trả lời với số điểm thấp nhất , như được xác định ở trên.


Hừm, tại sao không yêu cầu bộ giải mã cũng như bằng chứng cho thấy mã hóa thực sự hoạt động (và có thể hoàn nguyên)? Ngoài ra những gì về bao gồm những thứ như nén gzip tích hợp? Điều đó sẽ làm cho nó thực sự khó khăn để tìm ra kích thước nén trong trường hợp xấu nhất.
Martin Ender

@ m.buettner Đã chỉnh sửa. Tôi đã thêm một chút về các thư viện nén và một chút về bằng chứng về trường hợp xấu nhất. Tôi không thực sự muốn thực thi một bộ giải mã. Áp phích có thể bao gồm họ nếu họ muốn chứng minh giải pháp của họ, nhưng nó sẽ không được tính vào điểm số.
Geobits

Ồ vâng, tôi đã không đề nghị thêm chúng vào điểm số. Bạn vẫn có thể yêu cầu một bộ giải mã (vô dụng) làm bằng chứng. Điều đó làm cho nó dễ dàng hơn để kiểm tra xem đệ trình có thể xử lý các trường hợp đặc biệt.
Martin Ender

@ m.buettner Bạn làm cho một điểm tuyệt vời. Giải mã nó là.
Geobits

2
The second player is in jail, and has been for one turn. I'm not sure why, since he has a GOoJF card, but he's there.Ở trong tù là một danh mục tốt vì bạn không trả tiền thuê nhà. :)
undergroundmonorail

Câu trả lời:


4

(Một câu trả lời đã được chỉnh sửa gần đây, điều này khiến tôi chú ý đến câu hỏi này và tôi đã quyết định dùng thử mặc dù đây là một câu hỏi cũ.)

Swift 1,2 - 1016 Điểm (2 * 81 + 854)

Đầu ra ở mức tồi tệ nhất 81 byte và thay đổi theo số lượng người chơi.

Một trong hai phương pháp làm việc. Phiên bản Playground dài hơn một chút.

Sân chơi nén

(Giả sử Input.txtlà trong Playground Documents Directory)

// Compressor e(inputFileName, outputFileName)
import Cocoa;typealias S=String;typealias U=UInt8;func e(a:S,b:S){var d=NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true)as![S],g=d[0],r=S(contentsOfFile:"\(g)/\(a)",encoding:4,error:nil)!.componentsSeparatedByString(";"),z=[U](count:4,repeatedValue:0),c=[U](),p:()->Int={r.removeAtIndex(0).toInt()!},f:()->Bool={r.removeAtIndex(0)=="true" ?true:false},j=U(p());c+=[(j<<4)|(U(p()))];for _ in 0..<j{if f(){c+=[255]}else{let(t,g,v)=(UInt16(p()),U(p()),U(p()));c+=[(U(p()))|(g<<2),v,U(t>>8),U(t&255)]}};for _ in 0..<28{c+=[(U(bitPattern:Int8(p()))<<4)|((f() ?1:0)<<3)|(U(p()))]};for h in 0..<16{let y=h>7 ?1:0,x=Int8(p()),w=Int8(p());c+=[(U(bitPattern:x)<<4)|(U(bitPattern:w)&15)];z[y]=z[y]<<1;if x == -1{z[y]|=1};z[y+1]=z[y+1]<<1;if w == -1{z[y+1]|=1}};NSData(bytes:c+z,length:c.count+4).writeToFile("\(g)/\(b)",atomically:true)}

// Decompressor d(inputFileName, outputFileName)
func d(a:S,b:S){var d = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)as![String],e=d[0],i=NSData(contentsOfFile:"\(e)/\(a)")!,n=[UInt8](count:i.length,repeatedValue:0),o="";i.getBytes(&n,length:i.length);let k=n.removeAtIndex(0),j=k>>4;o+="\(j);\(k&15);";for _ in 0..<j{let h=n.removeAtIndex(0);if h>>7 == 1{o+="true;";continue};let p=n.removeAtIndex(0),b=n.removeAtIndex(0),c=n.removeAtIndex(0);o+="false;\(UInt16(b)<<8|UInt16(c));\(h>>2);\(p);\(h&0b11);"};for _ in 0..<28{let p=Int8(bitPattern:n.removeAtIndex(0)),mortgage=((p>>3)&1)==1 ?"true":"false";o+="\(p>>4);\(mortgage);\(p&7);"};var m=[U](count:4,repeatedValue:0);for i in reverse(0..<4){m[i]=n.removeLast()};for h in 0..<16{var i=h>7 ?1:0,z=n.removeAtIndex(0),x=Int8(z>>4),y=Int8(z&15),isUnowned1=m[i]&128;m[i]=m[i]<<1;let isUnowned2=m[i+1]&128;m[i+1]=m[i+1]<<1;if isUnowned1 != 0 {x=(-1)};if isUnowned2 != 0 {y=(-1)};o+="\(x);\(y);"};o.writeToFile("\(e)/\(b)",atomically:true,encoding:4,error:nil)}

// Test function to compare the files
func t(a:S,b:S)->Bool{let d=NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)as![String],c=d[0],i=S(contentsOfFile:"\(c)/\(a)",encoding:4,error:nil)!,j=S(contentsOfFile:"\(c)/\(b)",encoding:4,error:nil)!;return i==j}
// Usage
e("Input.txt", "Output.bin")  // Encode
d("Output.bin", "Output.txt") // Decode
t("Input.txt", "Output.txt")  // Test -> Should output 'true'

Compress.swift - chạy trong Terminal bằngswift Compress.swift

(Giả sử Input.txtlà trên Desktop)

// Compressor - 854 Bytes
import Cocoa;typealias S=String;typealias U=UInt8;func e(a:S,b:S){var d=NSSearchPathForDirectoriesInDomains(.DesktopDirectory,.UserDomainMask, true)as![S],g=d[0],r=S(contentsOfFile:"\(g)/\(a)",encoding:4,error:nil)!.componentsSeparatedByString(";"),z=[U](count:4,repeatedValue:0),c=[U](),p:()->Int={r.removeAtIndex(0).toInt()!},f:()->Bool={r.removeAtIndex(0)=="true" ?true:false},j=U(p());c+=[(j<<4)|(U(p()))];for _ in 0..<j{if f(){c+=[255]}else{let(t,g,v)=(UInt16(p()),U(p()),U(p()));c+=[(U(p()))|(g<<2),v,U(t>>8),U(t&255)]}};for _ in 0..<28{c+=[(U(bitPattern:Int8(p()))<<4)|((f() ?1:0)<<3)|(U(p()))]};for h in 0..<16{let y=h>7 ?1:0,x=Int8(p()),w=Int8(p());c+=[(U(bitPattern:x)<<4)|(U(bitPattern:w)&15)];z[y]=z[y]<<1;if x == -1{z[y]|=1};z[y+1]=z[y+1]<<1;if w == -1{z[y+1]|=1}};NSData(bytes:c+z,length:c.count+4).writeToFile("\(g)/\(b)",atomically:true)}
// Decompressor
func d(a:S,b:S){var d = NSSearchPathForDirectoriesInDomains(.DesktopDirectory,.UserDomainMask,true)as![String],e=d[0],i=NSData(contentsOfFile:"\(e)/\(a)")!,n=[UInt8](count:i.length,repeatedValue:0),o="";i.getBytes(&n,length:i.length);let k=n.removeAtIndex(0),j=k>>4;o+="\(j);\(k&15);";for _ in 0..<j{let h=n.removeAtIndex(0);if h>>7 == 1{o+="true;";continue};let p=n.removeAtIndex(0),b=n.removeAtIndex(0),c=n.removeAtIndex(0);o+="false;\(UInt16(b)<<8|UInt16(c));\(h>>2);\(p);\(h&0b11);"};for _ in 0..<28{let p=Int8(bitPattern:n.removeAtIndex(0)),mortgage=((p>>3)&1)==1 ?"true":"false";o+="\(p>>4);\(mortgage);\(p&7);"};var m=[U](count:4,repeatedValue:0);for i in reverse(0..<4){m[i]=n.removeLast()};for h in 0..<16{var i=h>7 ?1:0,z=n.removeAtIndex(0),x=Int8(z>>4),y=Int8(z&15),isUnowned1=m[i]&128;m[i]=m[i]<<1;let isUnowned2=m[i+1]&128;m[i+1]=m[i+1]<<1;if isUnowned1 != 0 {x=(-1)};if isUnowned2 != 0 {y=(-1)};o+="\(x);\(y);"};o.writeToFile("\(e)/\(b)",atomically:true,encoding:4,error:nil)}
func t(a:S,b:S)->Bool{let d=NSSearchPathForDirectoriesInDomains(.DesktopDirectory,.UserDomainMask,true)as![String],c=d[0],i=S(contentsOfFile:"\(c)/\(a)",encoding:4,error:nil)!,j=S(contentsOfFile:"\(c)/\(b)",encoding:4,error:nil)!;return i==j}
e("Input.txt", "Output.bin")
d("Output.bin", "Output.txt")
println(t("Input.txt", "Output.txt"))

Đầu vào / đầu ra mẫu

3;1;false;1534;0;14;0;false;34;1;10;1;true;1;false;1;1;false;0;0;true;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;3;12;6;9;4;-1;4;8;4;2;9;5;11;10;14;7;

.

31 00 0E 05 FE 05 0A 00 22 FF 11 10 08 F0 F0 F0
F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 F0 
F0 F0 F0 F0 F0 F0 01 23 45 67 89 AB CD EF 3C 69 
4F 48 42 95 BA E7 00 00 20 00

4

Pure C (3592 điểm)

Đầu ra là 182 byte. Kích thước là O (1), vì vậy đây là trường hợp xấu nhất.

Điều này sử dụng sscanf rộng rãi để đọc các tập tin và chỉ cần bỏ các cấu trúc vào đĩa.

Tôi đã phải sửa đổi một chút đầu vào, vì ví dụ của bạn không bao gồm 28 thuộc tính.

Đối với các biến, tôi đặt tên chúng từ chữ cái đầu tiên của nó là gì, hoặc nếu điều đó sẽ xung đột, thì chữ cái thứ hai (hoặc tiếp theo). Ví dụ: Trò chơi, Người chơi, Người chơi, v.v.

nén.c (680 byte):

#import <stdio.h>
#import <stdint.h>
#define T(X) for(int i=0;i<(X);i++)
typedef uint8_t U;typedef struct{U p;U t;U a[16];U e[16];}G;typedef struct{U b;uint16_t m;U c;U p;U t;}L;typedef struct{int8_t o;U m;U i;}R;G g;L l[8];R r[28];main(){FILE *f=fopen("input.txt","r");fscanf(f,"%d;%d;",&g.p,&g.t);T(g.p){l[i].b=(fgetc(f)=='t');while(fgetc(f)!=';');if(!l[i].b){fscanf(f,"%d;%d;%d;%d;",&l[i].m,&l[i].c,&l[i].p,&l[i].t);}}T(28){fscanf(f,"%d;",&r[i].o);r[i].m=(fgetc(f)=='t');while(fgetc(f)!=';');fscanf(f,"%d;",&r[i].i);}T(16){fscanf(f,"%d;",&g.a[i]);}T(16){fscanf(f,"%d;",&g.e[i]);}f=fopen("c.dat","w");fwrite(&g,sizeof(G),1,f);fwrite(&l,sizeof(L),8,f);fwrite(&r,sizeof(R),28,f);}

nén.c (tiền golf)

#include "m.h"

#define NEXT_FIELD b=strchr(b,';')+1;

G g;
L l[8];
R r[28];

char a[1024];
char *b = a;

main() {
    FILE *i = fopen("input.txt", "r");
    fgets(a, 1024, i);
    fclose(i);

    sscanf(b, "%d;%d;", &g.p, &g.t);
    NEXT_FIELD NEXT_FIELD

    TIMES(g.p) {
        l[i].b = (*b == 't'); NEXT_FIELD
        if(!l[i].b) {
            sscanf(b, "%d;%d;%d;%d;", &l[i].m, &l[i].c, &l[i].p, &l[i].t);
            NEXT_FIELD NEXT_FIELD NEXT_FIELD NEXT_FIELD
        }
    }

    TIMES(28) {
        sscanf(b, "%d;", &r[i].o); NEXT_FIELD
        r[i].m = (*b == 't'); NEXT_FIELD
        sscanf(b, "%d;", &r[i].i); NEXT_FIELD
    }

    TIMES(16) {
        sscanf(b, "%d", &g.a[i]);
        NEXT_FIELD
    }

    TIMES(16) {
        sscanf(b, "%d", &g.e[i]);
        NEXT_FIELD
    }

    FILE *c = fopen("c.dat", "w");
    fwrite(&g, sizeof(G), 1, c);
    fwrite(&l, sizeof(L), 8, c);
    fwrite(&r, sizeof(R), 28, c);
    fclose(c);
}

giải nén.c :

#import <stdio.h>
#import <stdint.h>

#define T(X) for(int i = 0; i < (X); i++)
typedef uint8_t U;

typedef struct {
    U p;
    U t;
    U a[16];
    U e[16];
} G;
typedef struct {
    U b;
    uint16_t m;
    U c;
    U p;
    U t;
} L;
typedef struct {
    int8_t o;
    U m;
    U i;
} R;

G g;
L l[8];
R r[28];

main() {
    FILE *c = fopen("c.dat", "r");
    fread(&g, sizeof(G), 1, c);
    fread(&l, sizeof(L), 8, c);
    fread(&r, sizeof(R), 28, c);
    fclose(c);

    FILE *d = fopen("output.txt", "w");

    fprintf(d, "%d;%d;", g.p, g.t);
    T(g.p) {
        fprintf(d, "%s;", l[i].b ? "true" : "false");
        if(!l[i].b){
            fprintf(d, "%d;%d;%d;%d;", l[i].m, l[i].c, l[i].p, l[i].t);
        }
    }
    T(28) {
        fprintf(d, "%d;%s;%d;", r[i].o, r[i].m ? "true" : "false", r[i].i);
    }
    T(16) { fprintf(d, "%d;", g.a[i] != 255 ? g.a[i] : -1); }
    T(16) { fprintf(d, "%d;", g.e[i] != 255 ? g.e[i] : -1); }

    fclose(d);
}

Đầu vào / đầu ra :

3;1;false;1546;0;14;0;false;7692;1;10;1;true;1;false;1;1;false;0;0;true;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;-1;false;0;0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;3;12;7;4;5;2;13;11;15;6;8;9;10;1;14;-1;

Được nén (182 byte):

0301 0001 0203 0405 0607 0809 0a0b 0c0d
0e0f 030c 0704 0502 0d0b 0f06 0809 0a01
0eff 0000 0a06 000e 0000 0000 0c1e 010a
0100 0100 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0100 0101 0000 0001 00ff 0000 ff00
00ff 0000 ff00 00ff 0000 ff00 00ff 0000
ff00 00ff 0000 ff00 00ff 0000 ff00 00ff
0000 ff00 00ff 0000 ff00 00ff 0000 ff00
00ff 0000 ff00 00ff 0000 ff00 00ff 0000
ff00 00ff 0000 

Chạy đi!

$ make compress decompress && ./compress && ./decompress && md5 input.txt output.txt
MD5 (input.txt) = fa655a5a17d67b188424ab0dcfdfb825
MD5 (output.txt) = fa655a5a17d67b188424ab0dcfdfb825

Cảm ơn, tôi đã cuộn tiêu đề vào để tiết kiệm một chút và cố định điểm của mình để đếm byte.
wjl

Có vẻ như bạn có thể lưu một số byte với mã hóa độ dài chạy sau. Không chắc nó khả thi đến mức nào nhưng nếu bạn thực hiện nó thông qua một byte thoát thì nó cũng sẽ hoạt động tốt với dữ liệu không lặp lại. Heh.
cjfaure
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.