Монопольне стиснення


17

Враховуючи рядок, що відображає поточний стан монополістичної гри на початку черги гравця, стисніть усі необхідні дані в найменший результат. Відповіді будуть судити за розміром виводу та розміром джерела .

Примітка. Є багато регіональних варіацій, але всі посилання в цій публікації на назви властивостей тощо базуються на цій дошці .


Вхід:

Введення буде подано у вигляді окремого ;розділеного рядка. Цей рядок надається програмі будь-яким способом, який є звичним для обраної вами мови, будь то stdin, аргументи тощо.

Неформатоване введення виглядає приблизно так:

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 (Virginia Ave)
  • не знаходиться у в'язниці

Другий гравець перебуває у в'язниці, і вже на одну чергу. Я не впевнений чому , оскільки він має карту GOoJF, але він там.

Третій гравець банкрут, і більше інформації не вимагається і не надається.

Властивості

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

Властивості перераховані по порядку навколо дошки, починаючи від Середземномор'я і закінчуючи на Boardwalk. Властивості, які не можуть бути власниками, не включені до цього списку, тому їх буде загалом 28. Рівень покращення 0означає непідтверджений. Рівень 1- це один будинок, до рівня 5для готелю. А -1для власника означає, що ним не належить жоден гравець.

Згідно зі стандартними правилами, майно, яке знаходиться під заставою, повинно бути власником і не повинно вдосконалюватися. Власність, яка вдосконалюється, повинна бути власником і не повинна бути закладена.

Крім того, для покращення властивості гравець повинен володіти усім кольоровим блоком. Для цілей цієї гри нам не байдуже, чи покращуються властивості "рівномірно".

Зауважте, що ці позиції не збігаються з позиціями гравців, наведеними вище. Наприклад, гравець на 5позиції опинився б на Reading Railroad, що є третім майном у списку (оскільки "Go", "Громадські скрині" та "Податок на прибуток" не можуть бути власниками). Позиції гравців проходять від 0(Перейти) за годинниковою стрілкою до 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;

Кожен з колод шансу і Community Chest має 16загальні карти. Цифри представлені так, як вони відображаються в поточно перетасованій колоді. У цьому прикладі першою карткою, яка витягла колоду Chance, буде карта 0, а за нею картка 1(хто перетасує цю колоду смокче). Перша карта витягнув із товариства грудей карти 3, а потім 12.

Не хвилюйтеся, що означає кожна картка (текст картки), за винятком картки 0. Це картка "Вийти з в'язниці" на цю колоду. Якщо гравець володіє ним, він буде в кінці списку, представленим як -1.


Вихід:

Ви повинні вивести (консолірувати, stdout або файл) представлення стану гри. Вона повинна включати всю інформацію, необхідну для представлення гри. Наприклад, ви можете опустити (або скоротити) невідомі властивості, оскільки вони не можуть бути ні поліпшеними, ні заставленими. Вхід не може опустити їх, тому що це невкладений список.

Стиснення слід робити таким чином, щоб ви могли обчислити найгірший розмір виводу. Це може дискваліфікувати певні алгоритми стиснення (якщо ви не зможете довести найгірший випадок та навести приклад введення в гіршому випадку).

Якщо ваш вихідний код не є розумно багатослівним, поясніть, як представлена ​​гра. Відповіді, що складаються з нічого, крім програми для гольфу та стисненого виходу, не відмовляють. Наприклад, якщо ви опускаєте певні значення, поясніть, як можна отримати їх з результатів.


Оцінка / Правила:

Оцінка базується як на розмірі стиснення в гірших випадках у бітах , так і на розмірі вихідного коду в байтах :

score = (outputBits * 2) + encoderSourceBytes

Повна відповідь повинна містити:

  • Вихідний приклад
  • Джерело кодера
  • Джерело декодера (не рахується з балом)

Усі кодери повинні бути повноцінними програмами, а стандартні лазівки заборонені. Використання вбудованих або зовнішніх бібліотек стиснення також заборонено.

Переможець - це відповідь з найнижчою оцінкою, як визначено вище.


Гм, чому б не потрібно декодер, а також доказ того, що кодування насправді працює (і є реверсивним)? А як щодо включення таких речей, як вбудована стискання gzip? Це зробило б дуже важко визначити найгірший розмір стиснення.
Мартін Ендер

@ m.buettner Відредаговано. Я додав трохи про бібліотеки стиснення і трохи про доказ найгіршого випадку. Я не хочу дуже примусово застосовувати декодер. Плакати можуть включати їх, якщо вони хочуть довести своє рішення, але це не зараховується до оцінки.
Геобіт

О так, я не пропонував додавати їх до оцінки. Ви все-таки можете зажадати декодера (необов’язаний) як доказ. Це полегшує тест на те, чи можуть подані матеріали обробляти особливі справи.
Мартін Ендер

@ m.buettner Ви чудово оцінюєте. Дешифратори це.
Геобіт

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.Перебувати в тюрмі - це добре, бо ти не платиш оренду. :)
підземниймонорельс

Відповіді:


4

(Нещодавно була відредагована відповідь, яка принесла мені це питання, і я вирішив спробувати, хоча це старе питання.)

Швидкий 1,2 - 1016 балів (2 * 81 + 854)

Вихід становить у гіршому випадку 81 байт і змінюється в залежності від кількості гравців.

Будь-який із двох методів працює. Версія Playground трохи довша.

Стиснути ігровий майданчик

(Передбачається 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);
}

decpress.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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.