독점 압축


17

플레이어 차례가 시작될 때 독점 게임의 현재 상태를 나타내는 문자열이 주어지면 필요한 모든 데이터를 가장 작은 출력으로 압축하십시오. 답변은 출력 크기소스 크기 로 판단됩니다 .

참고 : 지역별로 많은 변형이 있지만이 게시물에서 속성 이름 등에 대한 모든 참조는 이 보드를 기반으로 합니다 .


입력:

입력은 하나의 ;분리 된 문자열로 제공됩니다. 이 문자열은 stdin, arguments 등 선택한 언어로 관습에 관계없이 프로그램에 제공됩니다.

형식화되지 않은 입력은 다음과 같습니다.

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)

형식화 된 입력 예 는 다음과 같습니다.

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;

조금씩 찍은 :

3;1;

3 명의 플레이어가 있으며, 플레이어 1의 차례입니다 (제로 인덱스, 두 번째 플레이어).

선수

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

첫 번째 플레이어 :

  • 파산하지 않다
  • 현금 $ 1546 보유
  • 징역 무료 카드 0 장 소지
  • 위치 14에 있습니다 (버지니아 애비뉴)
  • 감옥에 있지 않다

두 번째 플레이어 감옥에 있으며 한 차례입니다. 그가 GOoJF 카드를 가지고 있기 때문에 왜 그런지 잘 모르겠지만 거기에 있습니다.

세 번째 선수는 파산하며 더 많은 정보가 필요하지도 않습니다.

속성

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

속성은 지중해에서 시작하여 보드 워크에서 끝나는 보드 주변 순서대로 나열됩니다. 소유 할 수없는 속성은이 목록에 포함되지 않으므로 총 28 개가됩니다 0. 개선 수준 은 개선되지 않음을 의미합니다. 레벨 15호텔의 레벨까지 한 집 입니다. -1소유자의 A 는 플레이어가 소유하지 않은 것을 의미합니다.

표준 규칙에 따르면, 저당 부동산 해야한다 소유하고 해야하지가 개선 될 수있다. 개선 된 특성 해야한다 소유하고 저당한다.

또한 속성을 향상 시키려면 플레이어 전체 색상 블록을 소유 해야합니다 . 이 게임의 목적 상, 우리는 속성이 "균등하게"개선되는지 상관하지 않습니다.

이 위치는 위에 주어진 플레이어 위치와 동일 하지 않습니다 . 예를 들어, 해당 5직위 의 플레이어 는 목록 의 세 번째 자산 인 Reading Railroad에 있습니다 (Go, Community Chest 및 소득세를 소유 할 수 없기 때문에). 플레이어 위치는 0(Go)에서 39(Boardwalk) 까지 시계 방향으로 진행됩니다 .

카드

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;

기회와 커뮤니티 상자 덱에는 16총 카드가 있습니다. 숫자는 현재 셔플 데크에 나타나는대로 표시됩니다. 이 예에서, 찬스 덱에서 뽑은 첫 번째 카드는 card 0다음에 카드가 있습니다 1(해당 카드를 섞은 사람). 커뮤니티의 가슴에서 가져온 첫 번째 카드는 카드입니다 312.

card를 제외한 각 카드의 의미 (카드 텍스트) 에 대해 걱정하지 마십시오 0. 그것은 그 갑판에 대한 무료 탈옥 카드입니다. 플레이어가 소유 한 경우 목록의 끝에 표시됩니다 (로 표시됨) -1.


산출:

게임 상태의 표현을 (콘솔, stdout 또는 파일로) 출력해야합니다. 여기에는 게임을 나타내는 데 필요한 모든 정보가 포함되어야합니다 . 예를 들어, 소유되지 않은 부동산은 개선 또는 담보 대출을받을 수 없기 때문에 생략하거나 생략 할 수 있습니다. 인덱싱되지 않은 목록이므로 입력을 생략 할 수 없습니다.

최악의 경우 출력 크기를 계산할 수있는 방식으로 압축해야합니다. 최악의 경우를 증명할 수없고 최악의 경우 입력 예를 제공하지 않는 한 특정 압축 알고리즘을 사용할 수 없습니다.

소스 코드가 부당하게 장황 하지 않는 한 게임이 어떻게 표현되는지 설명하십시오. 골프 프로그램과 압축 출력으로 구성된 답변은 권장하지 않습니다. 예를 들어, 특정 값을 생략하는 경우 출력에서 ​​값을 파생시키는 방법을 설명하십시오.


점수 / 규칙 :

스코어링은 최악의 압축 크기 ( 비트 )와 소스 코드 크기 ( 바이트)를 기반으로합니다 .

score = (outputBits * 2) + encoderSourceBytes

완전한 답변은 다음을 포함해야합니다.

  • 출력 예
  • 인코더 소스
  • 디코더 소스 (점수에 포함되지 않음)

모든 엔코더는 완전한 프로그램이어야하며 표준 허점 은 금지되어 있습니다. 내장 또는 외부 압축 라이브러리를 사용하는 것도 금지됩니다.

승자는 위에서 정의한대로 가장 낮은 점수를 얻은 답입니다 .


흠, 왜 인코딩이 실제로 작동하고 되돌릴 수 있다는 증거뿐만 아니라 디코더가 필요하지 않습니까? 또한 내장 gzip 압축과 같은 것을 포함하는 것은 어떻습니까? 최악의 압축 크기를 파악하기가 정말 어렵습니다.
마틴 엔더

@ m.buettner 편집했습니다. 압축 라이브러리와 최악의 증거에 대해 조금 추가했습니다. 나는 실제로 디코더를 시행하고 싶지 않습니다. 포스터는 자신의 솔루션을 증명하기 위해 포함시킬 수 있지만 점수에 포함되지 않습니다.
Geobits

예, 점수에 추가하라고 제안하지 않았습니다. 증거로 여전히 (고용되지 않은) 디코더가 필요할 수 있습니다. 따라서 제출이 특수 사례를 처리 할 수 ​​있는지 여부를 쉽게 테스트 할 수 있습니다.
마틴 엔더

@ m.buettner 당신은 훌륭한 지적을합니다. 디코더입니다.
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.임대료를 지불하지 않기 때문에 감옥에 갇히는 것이 좋습니다. :)
undergroundmonorail

답변:


4

(최근에 답변이 편집되어이 질문에주의를 기울였으며, 오래된 질문이지만 시도해보기로 결정했습니다.)

스위프트 1.2-1016 포인트 (2 * 81 + 854)

출력은 최악의 81 바이트이며 플레이어 수에 따라 변경됩니다.

두 가지 방법 중 하나가 작동합니다. 놀이터 버전이 약간 더 깁니다.

운동장 압축

(가정합니다 Input.txt이다 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- 터미널을 사용하여 실행swift Compress.swift

(가정은 Input.txt온이다 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"))

샘플 입력 / 출력

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

순수한 C (3592 포인트)

출력은 182 바이트입니다. 크기는 O (1)이므로 최악의 경우입니다.

이것은 sscanf를 광범위하게 사용하여 파일을 읽고, 구조체를 디스크에 덤프합니다.

예제에 28 개의 속성이 포함되어 있지 않으므로 입력을 약간 수정해야했습니다.

변수의 경우, 나는 그것이 무엇인지의 첫 번째 문자에서, 또는 그것이 충돌하는 경우 두 번째 (또는 그 이후의) 문자에서 그 이름을 지정했습니다. 예를 들어 Game, pLayer, pRoperty 등

compress.c (680 바이트) :

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

compress.c (사전 골프)

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

decompress.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);
}

입 / 출력 :

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;

압축 (182 바이트) :

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 

그것을 실행하십시오!

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

감사합니다. 비트를 저장하기 위해 헤더를 굴리고 바이트를 계산하도록 점수를 수정했습니다.
wjl

실행 길이 인코딩으로 바이트를 절약 할 수있는 것 같습니다. 그것이 가능한지 확실하지 않지만 이스케이프 바이트를 통해 수행하면 반복되지 않는 데이터와도 잘 작동합니다. 허.
cjfaure
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.