Codieren Sie ein Bild innerhalb der Quelle

10

Die Golf-Herausforderung besteht darin, das folgende Bild in einer Quelldatei zu codieren und zu komprimieren.

Bild

Um dies zu tun Sie müssen 3 Funktionen schreiben: red, greenund bluedie akzeptieren x / y - Koordinaten des Bildes und gibt die entsprechenden R / G / B - Pixel - Wert zwischen 0-255.

Hier ist der C / C ++ - Testcode:

#include <stdio.h>
#include "your_file"
int main() {
  int x, y;
  for(y = 0; y < 32; ++y)
  for(x = 0; x < 32; ++x)
    printf("%i %i %i\n", red(x, y), blue(x, y), green(x, y));
}

Und die Ausgabe: http://pastebin.com/A770ckxL (Sie können dies verwenden, um Ihre Bilddaten zu generieren)

Regeln & Details:

  • Dies ist ein Golf
  • Nur Ihr Code / Ihre Datei wird mit Golf gespielt - der Testcode ist separat
  • Der verwendete Zeichensatz ist ASCII. Steuerzeichen in Zeichenfolgen dürfen jedoch nur verwendet werden, wenn sie maskiert sind (wie '\ n' und '\ r' usw.).
  • Alles muss in der Quelle enthalten sein - kein Laden von Dateien
  • Ihre Ausgabe muss mit der Beispielausgabe übereinstimmen. Dies bedeutet verlustfreie Komprimierung.

Sprachen:

Das Problem wurde mit Blick auf C / C ++ geschrieben, aber ich entferne diese Einschränkungen. Trotzdem werde ich immer noch empfehlen, sie zu verwenden.

Pubby
quelle
4
Wenn es keinen bestimmten Grund dafür gibt, wird dringend davon abgeraten, eine Frage auf eine bestimmte Sprache festzulegen. Was ist der Grund, warum man keine anderen Sprachen benutzen darf?
FUZxxl
3
Wenn eine Lösung weniger interessant ist, stimmen Sie sie nicht ab. Das Verbot von "lahmen" Lösungen durch Ausschließen von Sprachen ist übertrieben.
FUZxxl
2
Wenn Sie den Zeichensatz bereits auf ASCII beschränkt haben (was ich für absolut in Ordnung halte), wie können wir Unicode-Hacks verwenden? Was Basis 64 betrifft, können Sie dies sowohl in Standard C als auch in jeder anderen Sprache tun, es gibt nur unterschiedliche Mengen an Wrapper-Code. - Aber ich mag die Aufgabe.
hörte auf, gegen den Uhrzeigersinn am
1
Hmm, was ist mit den ASCII-Steuerzeichen 0-31 (und 127)? Technisch gesehen sind sie Teil von ASCII, aber sind sie erlaubt? Und wenn nicht, hoffe ich, dass zumindest für das LF-Zeichen (10) eine Ausnahme gemacht wird, und vielleicht auch für CR (13) und TAB (9)?
Ilmari Karonen
1
Wenn Sie Ihre neue Version also buchstäblich lesen, müssen sich alle Lösungen in einer Zeile befinden, da nicht verschobene Zeilenvorschübe nicht zulässig sind. Ist das wirklich das, was du vorhast?
Ilmari Karonen

Antworten:

6

C, 796 754 712 703 692 685 682 670 666 662 656 648 Zeichen

Änderungsprotokoll:

  • 754-> 712: hinzugefügt , returnum das #define, ersetzt ifmit ?Anweisungen (dank @FUZxxl), das Entfernen intvon den Funktionen Parameterliste.
  • 712-> 703: Schamlose Kopie von bunnit wieder :) Verschob die gesamte Bilderstellung in die #define
  • 703-> 692: Zusammengeführt p[]und h[]einige weitere ?:Verbesserungen
  • 692-> 685: Inkrementieren bso iwird nicht mehr benötigt. m=bstatt m=11und n<2e3statt i<356- diese sind nahe an undefiniertem Verhalten / Speicherbeschädigung, aber es scheint, ich habe Glück :)
  • 685-> 682: kist jetzt (32,16,8,4,2,1,0) anstelle von (5,4,3,2,1,0). Gotcha, DC;)
  • 682-> 670: Split p[]und h[], umgewandelt h[]in a char*- awwww, ist ein schläfriges Kätzchen drin^<+_=>-
  • 670-> 666: while=> for, l=l*2+...=>l+=l+...
  • 666-> 662: m=m>9?...=>c[n++]=m>9?...
  • 662-> 656: Umgekehrte Bitreihenfolge b[], sodass wir 64-127 anstelle von 0-63 zuordnen können und keinen Bitindex mehr benötigen k. Danke @Piotr Tarsa . Ersetzt ?:(GCC-Erweiterung) durch ||. Danke @JamesB
  • 656-> 648: Schamlose Kopie von Shelwien :) (Konstanten mit mehreren Zeichen für p[])

Das Bild wird in eine Base64-ähnliche Zeichenfolge (ASCII 37-100) konvertiert, wobei die Huffman-Codierung verwendet wird, um die Farben 0-9 mit 3-6 Bit und eine Sonderfarbe 10 (Pixel ist dieselbe wie die vorherige) mit nur 1 Bit zu codieren.

#define P (x,y){for(;n<2e3;j/=2){j>1||(j=*b+++27);l+=l+(j&1);for(m=0;m<11;m++)l-h[m]+32||(c[n++]=m>9?c[n-1]:m,l=0,m=b);}return 255&p[c[x+y*32]]
char*h="$^<+_=>-,* ",*b="F0(%A=A=%SE&?AEVF1E01IN8X&WA=%S+E+A-(,+IZZM&=%]U5;SK;cM84%WE*cAZ7dJT3R.H1I2@;a^/2DIK&=&>^X/2U*0%'0E+;VC<-0c>&YU'%],;]70R=.[1U4EZ:Y=6[0WU4%SQARE0=-XDcXd_WW*UAF&cFZJJ0EV*(a(P05S3IXA>51cH:S5SAE6+W%/[]7SF(153UM]4U()(53DA+J:]&5+5KX,L6>*4I,/UMBcML9WKLa9%UYIHKWW(9-*):(-ZW(9%T'N&9;C,C/Ea/Y7(JJ\\6CD9E,2%J*,ac]NIW8(M=VFac)/^)?IS-;W&45^%*N7>V,,C-4N35FMQaF,EaWX&*EJ4'";p[]={0,'R@+','aXL',7783255,'4k`',16354410,'NNv',5295994,4671418,9975021},c[1024],j,l,m,n;red P;}blue P>>16;}green P>>8;}

Kopierte zwei Dinge aus Bunnits Antwort, wobei das #defineund das gesamte Bild jedes Mal vollständig dekodiert werden, wenn red/ green/ blueaufgerufen wird. Es gibt Raum für zusätzliche Verbesserungen, also erwarten Sie einige Updates :) Ich bin mir nicht sicher, ob der Code eingehalten wird. GCC 4.6.1 wurde zum Kompilieren und Testen verwendet.

In Bezug auf die Komprimierung denke ich, dass arithmetische Codierung hilfreich wäre, da die Verteilung ziemlich verzerrt ist, aber möglicherweise wäre der Code-Overhead in diesem Fall zu hoch. Das LZW sollte auch sehr gute Arbeit leisten. Die Farben sind ziemlich lokal, daher könnte eine adaptive Codierung eine Idee sein.

Mehr lesbare 754-Zeichen-Version mit einigen Kommentaren:

#define P 255&p[c[x+y*32]]
// Base64 coded image bitstream, ASCII 37-100
// Huffman codes: 100, 111110, 11100, 1011, 111111, 11101, 11110, 1101, 1100, 1010, 0
char b[]="FYU%3+3+%B&E;3&HF1&Y1.JWXE83+%B=&=3)U]=.PP*E+%,('?B>?D*Wa%8&MD3P7dNbARIV1.Q[?4L9Qc.>E+EKLX9Q(MY%5Y&=?HC_)YDKE0(5%,]?,7YR+I@1(a&PO0+G@Y8(a%B23R&Y+)XcDXd<88M(3FEDFPNNY&HMU4UZY'BA.X3K'1DVOB'B3&G=8%9@,7BFU1'A(*,a(U-U'Ac3=NO,E'='>X]^GKMa.]9(*SD*^/8>^4/%(0.V>88U/)M-OU)P8U/%b5JE/?C]C9&4907UNN`GCc/&]Q%NM]4D,J.8WU*+HF4D-9L-;.B)?8Ea'L%MJ7KH]]C)aJA'F*24F]&48XEM&Na5";
// Colors, order GBR (one char shorter than all the others)
p[]={0,5390379,6379596,7783255,3435360,16354410,5131894,5295994,4671418,9975021};
// Huffman codes for colors 0-10
h[]={4,62,28,11,63,29,30,13,12,10,0};
// Array for image data
c[1024];
i,j,k,l,m,n;
red(int x,int y){
  while(i<356){
    k--;
    if (k<0) {
      j=b[i++]-37;
      k=5;
    }
    l*=2;
    if (j&(1<<k)) l++;
    for(m=0;m<11;m++){
      if(l==h[m]){
        if (m>9) m=c[n-1];
        c[n++]=m;
        l=0;
        m=12;
      }
    }
  }
  return P;
}
blue(int x,int y){return P>>16;}
green(int x,int y){return P>>8;}
Schnaader
quelle
Sehr schön, ich kann nicht glauben, dass ich nicht über die Verwendung von Base 64 nachgedacht habe. Ich denke, Sie können trotzdem einige Zeichen speichern, insbesondere in dieser Schleife. Funktioniert übrigens gut in VS2008.
Scott Logan
Ich denke, Sie können das intaus den Parameterlisten entfernen, um weitere Bytes zu entfernen.
FUZxxl
Wie wäre es m=m>9?c[n-1]:m;für if(m>9)m=c[n-1];?
FUZxxl
Und auch: if(k<0){j=b[i++]-37;k=5;}warum nicht k>=0?:(j=b[i++]-37,k=5);? (Dieser Code verwendet eine C-Erweiterung von gcc, x=a?:bist der gleiche wie x=a?a:b, mit dem Unterschied, dass a nur einmal ausgewertet wird.
FUZxxl
red(x,y){while(i<356){--k>=0?:(j=b[i++]-37,k=5);l*=2;if(j&(1<<k))l++;for(m=0;m<11;m++)l!=h[m]?:(m=m<=9?:c[n-1],c[n++]=m,l=0,m=12);}return P;}
FUZxxl
4

Python ( 684 592 Zeichen)

red,blue,green=[lambda x,y,i=i:[15570996,2839104,7010700,5732035,6304875,0,12207943,8016079,7753294,5005656][int('eJxtkgGSxSAIQ6+kaLTe/2JLImj7Z9MZ6/gMIgjAzMbVWisGySRNm2ut5Hhx/2M0JMfHH5PWwo9x4mNO8pb6JkFM3hpqrR4+qY6eVK1mjlsFeSOBjPyCMy3348aXVRtq9X8czovMIwA5FeXKtGOcvfcf/lbvyW0n2BTOh122HiIH0g/uNrx47zupzMxuuTv808pZd3K7deJ/+PiH61AztmaNwPAsOnNGYovWIxswRill6vnAL4HgxDF17jFcjwRk/5b3Q1x1flLI9n64CIci8bmQe7NL8XoKliu+Jk/AR9rnjkwAYaDka8OXu/a+5NvvNzkcmqifL47H04kAz9M+9slKkDMGuOHi5PR7GZwv7MeApkz5JOSPHFVW3QTbzDJtzDIczkuWjeupLbckLyU5/gByftMg'.decode('base64').decode('zip')[32*y+x])]>>i&255 for i in 16,8,0]

Da diese Herausforderung nun für alle offen ist, warum nicht! Es ist die bekannte zlib -> base64-Codierungsroute, also entschuldige ich mich dafür. Hoffentlich wird ein Eintrag mit etwas Einfallsreichtum kürzer!

Hier ist ein Testausschnitt analog zum Original:

for y in range(32):
    for x in range(32):
        print red(x,y), blue(x,y), green(x,y)
Dillon Cower
quelle
Sie sollten versuchen, eine spezielle Farbe hinzuzufügen, um auch den vorherigen Pixelwert zu wiederholen. 588 Zeichen base64 ist viel größer als die Zeichenfolge in meiner Antwort (365 Zeichen), und obwohl zLib hier übertrieben ist, sollte es ein ähnliches Ergebnis liefern, sodass auf diese Weise insgesamt etwa 500 Zeichen möglich sein sollten.
Schnaader
4

C ++, 631 Zeichen; C - 613

Ein unärer MTF-Codierer der Basis 92, C ++, 631 Zeichen:

#define A(Z)int Z(int X,int Y){char*s="xdGe*V+KHSBBGM`'WcN^NAw[,;ZQ@bbZVjCyMww=71xK1)zn>]8b#3&PX>cyqy@6iL?68nF]k?bv/,Q`{i)n[2Df1zR}w0yIez+%^M)Diye{TC]dEY\\0,dU]s'0Z?+bo;7;$c~W;tvFl%2ruqWk$Rj0N[uP)fSjk?Tnpn_:7?`VbJ%r@7*MQDFCDo3)l#ln<kuRzzHTwCg&gYgSXtv\\m_Eb}zRK7JK<AZzOe}UX{Crk)SyBn;;gdDv=.j*O{^/q6)`lHm*YYrdM/O8dg{sKW#[email protected]#viYL$-<EU*~u5pe$r:`b)^dgXOJtf4";int*v,B=92,R=1,C=0,w[]={0,16354410,4671418,'aXL',7783255,5295994,'R@+','4k`',9975021,'NNv'};for(X+=Y*32+1;X--;)for(v=w;;){for(Y=*v++;R<B*B*B;C=C%R*B+*s++-35)R*=B;if(R/=2,C>=R){for(C-=R;--v>w;*v=v[-1]);*v=Y;break;}}return 255&Y
A(red);}A(blue)>>16;}A(green)>>8;}

Und die C-Version von oben (613 Zeichen):

#define A (X,Y){char*s="xdGe*V+KHSBBGM`'WcN^NAw[,;ZQ@bbZVjCyMww=71xK1)zn>]8b#3&PX>cyqy@6iL?68nF]k?bv/,Q`{i)n[2Df1zR}w0yIez+%^M)Diye{TC]dEY\\0,dU]s'0Z?+bo;7;$c~W;tvFl%2ruqWk$Rj0N[uP)fSjk?Tnpn_:7?`VbJ%r@7*MQDFCDo3)l#ln<kuRzzHTwCg&gYgSXtv\\m_Eb}zRK7JK<AZzOe}UX{Crk)SyBn;;gdDv=.j*O{^/q6)`lHm*YYrdM/O8dg{sKW#[email protected]#viYL$-<EU*~u5pe$r:`b)^dgXOJtf4";int*v,B=92,R=1,C=0,w[]={0,16354410,4671418,'aXL',7783255,5295994,'R@+','4k`',9975021,'NNv'};for(X+=Y*32+1;X--;)for(v=w;;){for(Y=*v++;R<B*B*B;C=C%R*B+*s++-35)R*=B;if(R/=2,C>=R){for(C-=R;--v>w;*v=v[-1]);*v=Y;break;}}return 255&Y
red A;}blue A>>16;}green A>>8;}

Nur um einen Eintrag mit Basis-95-Daten und arithmetischer Codierung + adaptivem statistischen Modell aufzunehmen.
Der Code von Schnaader verwendet ~ 438 Zeichen für Daten und nur 318 (311 ohne Maskierung).
Aber wie erwartet ist die arithmetische Codierung für eine kleine Stichprobe wie diese zu kompliziert.

(Dies sind 844 Zeichen)

char* q="q^<A\">7T~pUN1 adz824K$5a>C@kC8<;3DlnF!z8@nD|9D(OpBdE#C7{yDaz9s;{gF[Dxad'[oyg\\,j69MGuFcka?LClkYFh=:q\\\\W(*zhf:x)`O7ZWKLPJsP&wd?cEu9hj 6(lg0wt\\g[Wn:5l]}_NUmgs]-&Hs'IT[ Z2+oS^=lwO(FEYWgtx),)>kjJSIP#Y?&.tx-3xxuqgrI2/m~fw \\?~SV={EL2FVrDD=1/^<r*2{{mIukR:]Fy=Bl.'pLz?*2a? #=b>n]F~99Rt?6&*;%d7Uh3SpLjI)_abGG$t~m{N=ino@N:";
#define I int
#define F(N) for(i=0;i<N;i++)
#define Z C=(C%T)*B+(*q++)-32
enum{B=95,H=1024,T=B*B*B};I p[B],v[B+H],n=3,*m=&v[B],R=T*B,C,i,j,y,c,x,w;void D(I P){w=(R>>11)*P;(y=C>=w)?R-=w,C-=w:R=w;while(R<T)R*=B,Z;}struct u{u(){F(4)Z;F(B)p[i]=H,v[i]=0;F(H){v[0]=m[i-1];v[1]=m[i-32];j=i;F(n){I&P=p[i];D(P);if(y){P-=P>>4;c=v[i];goto t;}else P+=H+H-P>>4;}c<<=7;for(x=-255;x<0;x+=x+y)D(H);v[n++]=c=x;t:m[i=j]=c;}}}d;I red(I x,I y,I z=0){return m[y*32+x]>>z&255;}
#define blue(x,y) red(x,y,8)
#define green(x,y) red(x,y,16)

Tests (von früherer Base-96-Version):
http://codepad.org/qrwuV3Oy
http://ideone.com/ATngC

Irgendwie isst SO 7F-Codes, also musste ich es auf base = 95 aktualisieren

Shelwien
quelle
3

C ++ - 1525 1004 964 Zeichen

#define e (int x,int y){for(i=g=0;i<702;i=i+2)for(j=48;j<d[i];++j)c[g++]=d[i+1]-48;return 255&z[c[x+y*32]]
int i,g,j,z[]={0,7010700,12207943,5005656,5732035,8016079,2839104,6304875,15570996,7753294},c[1024];
char*d="3031;23322337261524453223310625132101214103453101233722172643310323342102521229492333210352112241036141014821042552621241014161016141024121022103210151015104526211034361034726510352625107441:530855425201511551045378554>55755312410242035201510528725212044451015411032:73135216561321012171017101725313581125152572531358122415257257110213310131231422022172025105110315322103210623815203110113053521053223817506920721013361322282530991062101213361322282520491049682224133614121028101510291029;812341023342835694810582018841018356978194810842835193329781019482410542835192310193668399428454319362928102829843845331019263028101330441014382035104369285338101810284536334910291018534820283546891019102943883536";
int red e>>16;}
int blue e>>8;}
int green e;}

Erstellt ein Array z, in dem alle möglichen Farben als einzelne Ganzzahl gespeichert sind (r << 16 | g << 8 | b). Erstellt ein Array d, das {Betrag, Wert} speichert, der Wert ist die Position im Array z, der Betrag ist die Anzahl aufeinanderfolgender Pixel mit diesem Wert (dh 3,0 bedeutet, dass die Farbe t [0] in den nächsten 3 erscheint Pixel. Das tatsächliche Array von Pixeln (c) wird dann jedes Mal berechnet, wenn Rot aufgerufen wird. Der Wert im Array wird dann nach rechts verschoben und nach Bedarf UND-verknüpft, um die richtige Komponente zu erhalten.

Ich könnte wahrscheinlich ein paar weitere Zeichen (~ 50) speichern, indem ich mehr Muster aus dem Array herausnehme, wie definiert.

Bearbeiten 1 - hat das d-Array für ein char-Array geändert, wobei jeder Wert um 48 versetzt ist. Dies bedeutet, dass ich es als Zeichenfolge darstellen kann, die eine Menge Kommas spart.

Bearbeiten 2 - Hat einen größeren Teil der Funktionen in der define-Anweisung entfernt.

Scott Logan
quelle
Warum benutzt du nicht C? In C ist es möglich, den intint f(int x,int y)f(x,y)
Typnamen
@FUzxxl, ja, C wird fast immer kürzer als C ++ sein, aber ich benutze C nicht wirklich täglich und kenne nicht wirklich alle Nuancen, die zur Reduzierung der Länge verwendet werden können. Es macht mir sowieso nichts aus, zu gewinnen, ich versuche nur, andere C ++ - Antworten zu schlagen.
Scott Logan
3

Javascript, 696 694 Zeichen

Danke an Schnaader für 696 -> 694.

Ich habe mir ein anderes Codierungsformat vorgestellt, nämlich die Lauflängencodierung mit einer Farbnachschlagetabelle. Es funktioniert ganz gut, weil es weniger als 16 Farben gibt und sie weniger als 16 Mal hintereinander erscheinen. Daher passt jede Pixeldefinition einschließlich der Länge in ein Byte. Ich setze die Farbe in den oberen Teil des Bytes und die Anzahl in den unteren Teil.

Am Ende stellte sich heraus, dass die base64-Zeichenfolge länger war als ich erwartet hatte (472 Zeichen), aber das Dekodierungsprogramm ist wirklich kurz.

for(b=i=a=[];a&15||(a=atob("AxMrMyIzJxYlRDUiMwEmFSMBIUEBQzUBITMnEidGMwEjMyQBUhIi
SSkzIwFTEiFCAWNBAUEoASRVYhJCAUFhAWFBAUIhASIBIwFRAVEBVGISAUNjAUMnVgFTYlIBRxRaA1hF
UgJREVUBVHNYRV51VRNCAUICUwJRASV4UhICRFQBURQBI3oTUxJWFiMBIXEBcQFxUhNTGCEVJXVSE1MY
IhQldVIXARIzATEhEyQCInECUgEVARM1IgEjASaDUQITAREDNSUBNSKDcQWWAicBMWMxIoJSA5kBJgEh
MWMxIoJSApQBlIYiQjFjQSEBggFRAZIBkoshQwEyQ4JTloQBhQKBSAGBU5aHkYQBSIJTkTOShwGRhEIB
RYJTkTIBkWOGk0mCVDSRY5KCAYKSSINUMwGRYgOCATEDRAFBgwJTATSWgjWDAYEBglRjM5QBkgGBNYQC
glNkmAGRAZI0iFNjAQ==").charCodeAt(i++));b.push([0,16354410,4671418,6379596,77832
55,5295994,5390379,3435360,9975021,5131894][a-- >>4]));green=(red=function(c,d){
return b[32*d+c]>>this&255}).bind(16);blue=red.bind(8)

Hinweis: Ich habe den Code aufgeteilt, um eine gute Lesbarkeit zu gewährleisten. Es muss sich in einer Zeile befinden, um ausgeführt zu werden.

Testcode:

for(var y = 0; y < 32; ++y) {
    for(var x = 0; x < 32; ++x) {
        console.log(red(x, y), green(x, y), blue(x, y));
    }
}

Ich denke, das Beispielergebnis ist tatsächlich die Ausgabe von Rot, Grün, Blau (nicht Rot, Blau, Grün wie im ursprünglichen Testcode); das funktioniert bei mir sowieso so.

Kopieren
quelle
Versuchen Sie, das Palettenarray auf zu ändern [0,16354410,4671418,6379596,7783255,5295994,5390379,3435360,9975021,5131894]- dies spart 1 Zeichen und ist GBR-Reihenfolge anstelle von RGB.
Schnaader
@schnaader Danke. Ich liebe diese Mikrooptimierungen :-) Bearbeiten: Es wurden sogar 2 Zeichen gespart, weil ich in meiner Originalquelle zweimal Blau verwendet habe
Kopie
2

C ++, 1357 Zeichen

int i,j,C[]={0,0,0,106,249,140,186,71,71,76,97,88,87,118,195,122,80,207,43,82,64,96,52,107,237,152,52,118,78,78},E[]={30,31,112,33,22,33,72,61,52,44,53,22,33,10,62,51,32,10,12,14,10,34,53,10,12,33,72,21,72,64,33,10,32,33,42,10,25,21,22,94,92,33,32,10,35,21,12,24,10,36,14,10,14,82,10,42,55,26,21,24,10,14,16,10,16,14,10,24,12,10,22,10,32,10,15,10,15,10,45,26,21,10,34,36,10,34,72,65,10,35,26,25,10,74,41,105,30,85,54,25,20,15,11,55,10,45,37,85,54,145,57,55,31,24,10,24,20,35,20,15,10,52,87,25,21,20,44,45,10,15,41,10,32,107,31,35,21,65,61,32,10,12,17,10,17,10,17,25,31,35,81,12,51,52,57,25,31,35,81,22,41,52,57,25,71,10,21,33,10,13,12,31,42,20,22,17,20,25,10,51,10,31,53,22,10,32,10,62,38,15,20,31,10,11,30,53,52,10,53,22,38,17,50,69,20,72,10,13,36,13,22,28,25,30,99,10,62,10,12,13,36,13,22,28,25,20,49,10,49,68,22,24,13,36,14,12,10,28,10,15,10,29,10,29,118,12,34,10,23,34,28,35,69,48,10,58,20,18,84,10,18,35,69,78,19,48,10,84,28,35,19,33,29,78,10,19,48,24,10,54,28,35,19,23,10,19,36,68,39,94,28,45,43,19,36,29,28,10,28,29,84,38,45,33,10,19,26,30,28,10,13,30,44,10,14,38,20,35,10,43,69,28,53,38,10,18,10,28,45,36,33,49,10,29,10,18,53,48,20,28,35,46,89,10,19,10,29,43,88,35,36,10};int*Q(int n){for(i=0;1;i++){for(j=0;j<E[i]/10;j++){if(!n)return&C[E[i]%10*3];n--;}}}
#define red(x,y) Q(x+32*y)[0]
#define blue(x,y) Q(x+32*y)[1]
#define green(x,y) Q(x+32*y)[2]

Ein bisschen entblößt:

int C[]={0,0,0,106,249,140,186,71,71,76,97,88,87,118,195,122,80,207,43,82,64,96,52,107,237,152,52,118,78,78},
int E[]={30,31,112,33,22,33,72,61,52,44,53,22,33,10,62,51,32,10,12,14,10,34,53,10,12,33,72,21,72,64,33,10,32,33,42,10,25,21,22,94,92,33,32,10,35,21,12,24,10,36,14,10,14,82,10,42,55,26,21,24,10,14,16,10,16,14,10,24,12,10,22,10,32,10,15,10,15,10,45,26,21,10,34,36,10,34,72,65,10,35,26,25,10,74,41,105,30,85,54,25,20,15,11,55,10,45,37,85,54,145,57,55,31,24,10,24,20,35,20,15,10,52,87,25,21,20,44,45,10,15,41,10,32,107,31,35,21,65,61,32,10,12,17,10,17,10,17,25,31,35,81,12,51,52,57,25,31,35,81,22,41,52,57,25,71,10,21,33,10,13,12,31,42,20,22,17,20,25,10,51,10,31,53,22,10,32,10,62,38,15,20,31,10,11,30,53,52,10,53,22,38,17,50,69,20,72,10,13,36,13,22,28,25,30,99,10,62,10,12,13,36,13,22,28,25,20,49,10,49,68,22,24,13,36,14,12,10,28,10,15,10,29,10,29,118,12,34,10,23,34,28,35,69,48,10,58,20,18,84,10,18,35,69,78,19,48,10,84,28,35,19,33,29,78,10,19,48,24,10,54,28,35,19,23,10,19,36,68,39,94,28,45,43,19,36,29,28,10,28,29,84,38,45,33,10,19,26,30,28,10,13,30,44,10,14,38,20,35,10,43,69,28,53,38,10,18,10,28,45,36,33,49,10,29,10,18,53,48,20,28,35,46,89,10,19,10,29,43,88,35,36,10};
int*Q(int n){
  for(int i=0;1;i++){
    for(int j=0;j<E[i]/10;j++){
      if(!n)return&C[E[i]%10*3];
      n--;
    }
  }
}
#define red(x,y) Q(x+32*y)[0]
#define blue(x,y) Q(x+32*y)[1]
#define green(x,y) Q(x+32*y)[2]

Centhält die RGB-Werte für die zehn verschiedenen Farben des Bildes. Eenthält die Daten für das Bild, wobei jedes Element E[i]sowohl eine Wiederholungszahl E[i]/10als auch einen Farbindex codiert E[i]%10.

Keith Randall
quelle
: +1 Sie könnten ein paar Zeichen aus in der Schleife rasieren pastebin.com/2UY8H2qt
Pubby
1
Wenn Sie Ihre Lösung in C umbenennen (keine Codeänderungen erforderlich) und die Definitionen in Funktionen ohne Typnamen wie int red(x,y){R Q(x+32*y)[0]}(only # define` umwandeln return, können Sie möglicherweise mehr Zeichen rasieren.
FUZxxl
1
Irgendwie betrügt dies, da Rot, Blau und Grün keine Funktionen, sondern Makros sind.
FUZxxl
1
Dies implementiert eine Funktion und ist kürzer (1339 Bytes). Bitte beachten Sie, dass dieses Programm wahrscheinlich nur in alten C: hpaste.org/65584
FUZxxl
Ich habe alle Typinformationen aus der Quelle entfernt. Es ist noch gültig C.
FUZxxl
1

Python 3 (589 Zeichen)

import base64,zlib
red,blue,green=(lambda x,y,i=i:b'\xed\x984+R@j\xf9\x8cWv\xc3`4k\0\0\0\xbaGGzP\xcfvNNLaX'[zlib.decompress(base64.decodebytes(b'eJxtkgGSxSAIQxWN1vtfeEkEbf9sOmMdn0EEAZjZuFprxSCZpGlzrZUcL+5/jIbk+Phj0lr4MU58zEneUt8kiMlbQ63VwyfV0ZOq1cxxqyBvJJCRX3Cm5X7c+LJqQ63+j8N5kXkEIKeiXJl2jLP3/sPf6j257QSbwvmwy9ZD5ED6wd2GF+99J5WZ2S13h39aOetObrdO/A8f/3AdasbWrBEYnkVnzkhs0XpkA8YopUw9H/glEJw4ps49huuRgOzf8n6Iq85PCtneDxfhUCQ+F3JvdileT8FyxdfkCfhI+9yRCSAMlHxt+HLX3pd8+/0mh0MT9fPF8Xg6EeB52sc+WQlyxgA3XJycfi+D84X9GNCUKZ+E/JGjyqqbYJtZpo1ZhsN5ybJxPbXlluSlJMcf++8TIA=='))[32*y+x]*3+i]for i in(0,1,2))

Testcode

for y in range(32):
    for x in range(32):
        print(red(x,y), blue(x,y), green(x,y))

Basierend auf der Lösung von Dillon Cower

AMK
quelle
1

PHP (5,4) - 822

Ich habe dies absichtlich getan , ohne eine der eingebauten Komprimierungsfunktionen zu verwenden . Diese Lösung ist noch nicht fertig. Ich bin mir nicht sicher, ob ich aufgegeben habe. Ich sehe Verbesserungsmöglichkeiten, aber ich kann im Moment nicht die Zeit / Willenskraft finden, um das Ganze umzugestalten. Deshalb poste ich, was ich habe bisher.

Zeilenumbrüche + Kommentare, die für 822 Byte entfernt werden sollen.

// Colour map
$c=[0,16354410,4671418,6379596,7783255,5295994,5390379,3435360,9975021,5131894];

// Optimised RLE map
$r=array_merge(array_diff(range(10,89),[27,40,47,56,59,60,63,66,67,70,73,75,76,77,79,80,83,86]),[92,94,99,105,107,112,118,145]);

// Image data (base 70)
$e="CDsF<Fd]WPX<F0^VE0240GX02Fd;d_F0EFN0?;<onFE0H;2>0I404h0NZ@;>0460640>20<0E05050Q@;0GI0Gd`0H@?0eMqCjY?:51Z0QJjYu[ZD>0>:H:50Wk?;:PQ05M0ErDH;`]E0270707?DHg2VW[?DHg<MW[?c0;F032DN:<7:?0V0DX<0E0^K5:D01CXW0X<K7Ub:d03I3<A?Cp0^023I3<A?:T0Ta<>3I420A050B0Bt2G0=GAHbS0\:8i08Hbf9S0iAH9FBf09S>0YAH9=09IaLoAQO9IBA0ABiKQF09@CA03CP04K:H0ObAXK080AQIFT0B08XS:AHRm090BOlHI0";

// Expand image data
for($i=0;$i<352;$i++){$b=$r[ord($e[$i])-48];$l=(int)($b/10);while($l--)$d[]=$c[$b%10];}

// Colour retrieval functions
function red($x,$y){global$d;return$d[$x+$y*32]&0xff;}
function green($x,$y){global$d;return$d[$x+$y*32]>>8;}
function blue($x,$y){global$d;return($d[$x+$y*32]>>8)&0xff;}

Teststummel:

for ($y=0;$y<32;$y++) {
    for ($x=0;$x<32;$x++) {
        printf("%d %d %d\n", red($x, $y), blue($x, $y), green($x, $y));
    }
}

Die Komprimierung der Bilddaten selbst ist ziemlich gut, aber die Funktionen zum Abrufen von RGB-Werten beanspruchen 1/4 des Codes.

Ich verwende einen benutzerdefinierten Codierungsmechanismus für base70 + Lauflänge.

  1. Es gibt 10 einzigartige Farben
  2. Farben haben Lauflängen zwischen 1 und 14 (12 verwendet).
  3. Es gibt 120 mögliche Kombinationen.
  4. Es werden nur 70 einzigartige Lauf- / Farbkombinationen verwendet.

Die codierten Bilddaten verweisen auf den Array-Index eines RLE, der wiederum das Array von Farben indiziert. Ich bin mir nicht sicher, wie viel Overhead dies durch direktes Referenzieren der Farben addiert oder subtrahiert.

Da es 10 Farben (0 bis 9) gibt, werden RLEs als gespeichert run_length * 10 + colour_index. Geben Sie eine Reihe von Codierungen zwischen 10 und 145 an, ohne mit Optimierungen basierend auf der Farbreihenfolge zu experimentieren. (dh ich könnte den Bereich 19 bis 140 einstellen, indem ich die Farben 0 bis 5, 5 bis 9 und 9 bis 0 verschiebe - aber dies kann andere Auswirkungen haben)

Eine vorherige Antwort besagt, dass ihre codierten Daten 472 Bytes betragen. Meine codierten Bilddaten sind 352 Bytes, aber die Zwischen-RLE / Farbkarte (die nicht binär codiert ist) beträgt weitere 129 Bytes, was eine Gesamtsumme von 481 ergibt (sowie zusätzlichen Overhead für die Verbindung der beiden). Ich vermute jedoch, dass meine Methode für größere Bilder möglicherweise besser skaliert.

MACHEN:

  1. Untersuchen Sie die binäre Codierung der RLE-Karte
  2. Finden Sie einen Weg, um die Größe der Funktionen zu reduzieren. globalist eine Hündin, kann aber nicht auf Zeichenindizes für Konstanten zugreifen.
  3. Experimentieren Sie mit der Farbindexreihenfolge, um festzustellen, ob die RLE-Kartengröße bei längeren aufeinanderfolgenden Zahlenläufen reduziert werden kann
  4. Mögliche 64-Bit-spezifische Optimierungen der Farbkarte? (r0 << 56 | r1 << 48 | ...)?
  5. Experimentieren Sie mit vertikalem RLE, um festzustellen, ob dies zu einem kompakteren Satz von Codierungen führt.
  6. Bereichskodierung?
Leigh
quelle
1

C (gcc) , 602 Bytes

P[]={0,6982905,0xba4747,5003361,5751670,8048464,2834514,6318900,0xed3498,7753294},X[1024],*i,r,w;
#define u(d)i=X;for(char*I="56s-8-8_TKCL-8!UJ7!#%!9L!#8_,_W8!78A!0,-us87!:,#/!;%!%i!AN1,/!%'!'%!/#!-!7!&!&!D1,!9;!9_X!:10!a@v&5lM0+&\"N!D<lMvNPN6/!/+:+&!Kn0,+CD!&@!7x(6:,XT7!#(!(!(06:h#JKP06:h-@KP0^!,8!$#6A+-(+0!J!6L-!7!U=&+6!\"5LK!L-=(I\\+_!$;$-305z!U!#$;$-30+H!H[-/$;%#!3!&!4!4y3#9!.93:\\G!Q+)k!):\\e*G!k3:*84e!*G/!M3:*.!*;[>u3DB*;43!34k=D8!*153!$5C!%=+:!B\\3L=!)!3D;8H!4!)LG+3:Ep!*!4Bo:;!";w=*I-33,*I++;)for(r=w/10+1;r--;*i++=P[w%10]>>d&255);x=X[y*32+x];
red(x,y){u(16)}green(x,y){u(8)}blue(x,y){u(0)}

Probieren Sie es online aus!

Heruntergewirtschaftet

P[]={...},              The palette. Each entry is an integer on the form `RRGGBB`.
X[1024],                The buffer we unpack things into.
*i,r,w;                 Misc variables.
#define u(d)            Macro taking the number of bits to shift palette entries.
i=X;for(char*I="...";   Start at beginning of X for output, I is the encoded data.
                        Data was packed as ((R - 1) * 10) + P + 33, with R being
                        run-length and P the palette entry.
w=*I-33,*I++;)          Pick up encoded char, and check for end of data.
for(r=w/10+1;r--;       Get run-length from encoded byte.
*i++=P[w%10]>>d&255);   Get palette entry and extract colour given by d to store in X.
x=X[y*32+x];            Implicit return of the value at given coordinates.
red(x,y){u(16)}         The specific functions for each channel, calling u() for the
green(x,y){u(8)}        real work.
blue(x,y){u(0)}
Gastropner
quelle