Monopolkomprimierung


17

Komprimieren Sie alle erforderlichen Daten auf die kleinste Ausgabe, wenn Sie eine Zeichenfolge angeben, die den aktuellen Status eines Monopoly- Spiels zu Beginn des Zuges eines Spielers darstellt. Die Antworten werden von beurteilt werden Ausgabegröße und Quellengröße .

Hinweis: Es gibt viele regionale Unterschiede, aber alle Verweise in diesem Beitrag auf Eigenschaftsnamen usw. basieren auf dieser Tafel .


Eingang:

Die Eingabe erfolgt als einzelne, ;getrennte Zeichenfolge. Diese Zeichenfolge wird dem Programm auf die in der von Ihnen gewählten Sprache übliche Weise übergeben, unabhängig davon, ob es sich um stdin, Argumente usw. handelt.

Die unformatierte Eingabe sieht folgendermaßen aus:

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)

Ein Beispiel für eine formatierte Eingabe lautet wie folgt:

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;

Stück für Stück aufgenommen:

3;1;

Es gibt 3 Spieler, und es ist Spieler 1 an der Reihe (null-indexiert, also der zweite Spieler)

Spieler

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

Der erste Spieler:

  • ist nicht bankrott
  • hat $ 1546 Bargeld zur Hand
  • besitzt 0 aus dem Gefängnis entlassene Karten
  • ist auf Position 14 (Virginia Ave)
  • ist nicht im Gefängnis

Der zweite Spieler ist im Gefängnis und war für eine Runde. Ich weiß nicht warum , da er eine GOoJF-Karte hat, aber er ist da.

Der dritte Spieler ist bankrott und weitere Informationen werden weder benötigt noch gegeben.

Eigenschaften

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

Die Eigenschaften werden in der Reihenfolge um das Brett aufgelistet, beginnend mit Mittelmeer und endend an der Promenade. Eigenschaften, deren Eigentümer nicht sein kann, sind in dieser Liste nicht enthalten, sodass insgesamt 28 vorhanden sind. Verbesserungsstufe 0bedeutet nicht verbessert. Level 1ist ein Haus, bis zu Level 5für ein Hotel. Ein -1für Besitzer bedeutet, dass es keinem Spieler gehört.

Nach Standardregeln, eine Eigenschaft , die verpfändet muss im Besitz sein und darf nicht verbessert werden. Eine Immobilie, die verbessert wird, muss Eigentum sein und darf nicht verpfändet werden.

Außerdem muss ein Spieler den gesamten Farbblock besitzen , damit eine Eigenschaft verbessert werden kann . Für die Zwecke dieses Spiels ist es uns egal, ob die Eigenschaften "gleichmäßig" verbessert werden.

Beachten Sie, dass diese Positionen nicht mit den oben angegebenen Spielerpositionen übereinstimmen. Zum Beispiel wäre ein Spieler auf der 5Position bei Reading Railroad, der dritten Eigenschaft in der Liste (da Go, Community Chest und Income Tax nicht im Besitz sein können). Spielerpositionen laufen von 0(Go) im Uhrzeigersinn bis 39(Boardwalk).

Karten

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;

Jedes der Zufalls- und Community-Truhen-Decks hat 16Gesamtkarten. Die Zahlen werden so angezeigt, wie sie im aktuell gemischten Deck erscheinen. In diesem Beispiel ist die erste Karte, die aus dem Zufallsstapel gezogen wird, eine Karte 0, gefolgt von einer Karte 1(wer auch immer diesen Stapel gemischt hat, ist am Boden). Die erste Karte, die aus der Community-Truhe gezogen wird 3, ist dann die Karte 12.

Kümmere dich nicht darum, was jede Karte bedeutet (der Kartentext), außer für die Karte 0. Das ist die kostenlose Karte zum Verlassen des Gefängnisses für dieses Deck. Wenn ein Spieler es besitzt, wird es am Ende der Liste als dargestellt -1.


Ausgabe:

Sie müssen eine Darstellung des Spielstatus ausgeben (auf Konsole, Standardausgabe oder Datei). Dies muss alle Informationen enthalten, die für die Darstellung des Spiels erforderlich sind . Beispielsweise könnten Sie nicht im Besitz befindliche Immobilien weglassen (oder abkürzen), da sie weder verbessert noch verpfändet werden können. Die Eingabe kann sie nicht auslassen, da es sich um eine nicht indizierte Liste handelt.

Die Komprimierung sollte so erfolgen, dass Sie die Ausgabegröße im ungünstigsten Fall berechnen können. Dies kann bestimmte Komprimierungsalgorithmen disqualifizieren (es sei denn, Sie können den ungünstigsten Fall nachweisen und ein Beispiel für eine Eingabe im ungünstigsten Fall angeben).

Sofern Ihr Quellcode nicht unangemessen ausführlich ist, erklären Sie, wie das Spiel dargestellt wird. Antworten, die nur aus einem Golf-Programm und einer komprimierten Ausgabe bestehen, werden nicht empfohlen. Wenn Sie beispielsweise bestimmte Werte weglassen, erläutern Sie, wie Sie sie aus der Ausgabe ableiten können.


Wertung / Regeln:

Die Bewertung basiert sowohl auf der Worst-Case- Komprimierungsgröße in Bits als auch auf der Quellcodegröße in Bytes :

score = (outputBits * 2) + encoderSourceBytes

Eine vollständige Antwort muss enthalten:

  • Ausgabebeispiel
  • Encoder-Quelle
  • Decoderquelle (wird nicht mit der Punktzahl verrechnet)

Alle Encoder müssen vollständige Programme sein, und Standardlücken sind verboten. Die Verwendung von eingebauten oder externen Komprimierungsbibliotheken ist ebenfalls verboten.

Der Gewinner ist die Antwort mit der niedrigsten Punktzahl, wie oben definiert.


Hm, warum nicht einen Decoder sowie einen Beweis dafür benötigen, dass die Codierung tatsächlich funktioniert (und rückgängig gemacht werden kann)? Und was ist mit Sachen wie der integrierten GZIP-Komprimierung? Das würde es wirklich schwierig machen, die Komprimierungsgröße für den schlimmsten Fall herauszufinden.
Martin Ender

@ m.buettner Bearbeitet. Ich habe ein bisschen über Komprimierungsbibliotheken und ein bisschen über Beweise für den schlimmsten Fall hinzugefügt. Ich möchte einen Decoder nicht wirklich erzwingen. Poster können sie einbeziehen, wenn sie ihre Lösung beweisen möchten, dies wird jedoch nicht auf die Punktzahl angerechnet.
Geobits

Oh ja, ich habe nicht vorgeschlagen, sie der Partitur hinzuzufügen. Sie könnten immer noch einen (ungolfed) Decoder als Beweis benötigen. So können Sie leichter testen, ob die Einreichungen mit Sonderfällen umgehen können.
Martin Ender

@m.buettner Du machst einen hervorragenden Punkt. Decoder ist es.
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.Im Gefängnis zu sein ist eine gute Strategie, weil man keine Miete zahlt. :)
undergroundmonorail

Antworten:


4

(Eine Antwort wurde kürzlich bearbeitet, wodurch ich auf diese Frage aufmerksam wurde, und ich habe beschlossen, es zu versuchen, obwohl es eine alte Frage ist.)

Swift 1.2 - 1016 Punkte (2 * 81 + 854)

Die Ausgabe ist im schlimmsten Fall 81 Bytes und ändert sich mit der Anzahl der Spieler.

Beide Methoden funktionieren. Die Playground-Version ist etwas länger.

Spielplatz komprimieren

(Angenommen, Input.txtist in der 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 - im Terminal mit ausführenswift Compress.swift

(Angenommen, Input.txtist auf der 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"))

Sample Input / Output

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

Reines C (3592 Punkte)

Die Ausgabe beträgt 182 Bytes. Die Größe ist O (1), dies ist also der schlimmste Fall.

Dies verwendet sscanf ausgiebig, um die Dateien zu lesen, und speichert die Strukturen einfach auf der Festplatte.

Ich musste die Eingabe leicht modifizieren, da Ihr Beispiel 28 Eigenschaften nicht enthielt.

Für Variablen habe ich sie aus dem ersten Buchstaben des eigentlichen Buchstabens oder, falls dies zu Konflikten führen sollte, aus dem zweiten (oder nachfolgenden) Buchstaben benannt. Zum Beispiel Game, pLayer, pRoperty usw.

compress.c (680 Bytes):

#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 (vorgolfen)

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

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

Eingabe / Ausgabe :

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;

Komprimiert (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 

Starte es!

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

Danke, ich habe den Header eingerollt, um ein wenig zu sparen, und meine Punktzahl auf die Anzahl der Bytes korrigiert.
wjl

Sieht so aus, als könnten Sie einige Bytes mit Lauflängencodierung nachher sparen. Ich bin mir nicht sicher, wie machbar das ist, aber wenn Sie es über ein Escape-Byte tun, sollte es auch gut mit sich nicht wiederholenden Daten funktionieren. Heh.
cjfaure
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.