Encoder une image à l'intérieur de la source

10

Le défi du golf est d'encoder et de compresser l'image suivante dans un fichier source.

Image

Pour ce faire , vous devez écrire 3 fonctions: red, greenet bluequi acceptent x / y de l'image et renvoie la valeur de pixel R / G / B correspondant entre 0-255.

Voici le code de test C / C ++:

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

Et la sortie: http://pastebin.com/A770ckxL (vous pouvez l'utiliser pour générer vos données d'image)

Règles et détails:

  • C'est un golf
  • Seul votre code / fichier est joué - le code de test est séparé
  • Le jeu de caractères utilisé est ASCII, mais les caractères de contrôle dans les chaînes ne peuvent être utilisés qu'en cas d'échappement (comme '\ n' et '\ r', etc.)
  • Tout doit être contenu à l'intérieur de la source - aucun chargement de fichier
  • Votre sortie doit correspondre à l'exemple de sortie. Cela signifie une compression sans perte.

Langues:

Le problème a été écrit en pensant à C / C ++, mais je supprime ces restrictions. Cela dit, je recommanderai toujours de les utiliser.

Pubby
la source
4
S'il n'y a aucune raison spécifique de le faire, il est fortement déconseillé de poser une question dans une langue spécifique. Quelle est la raison pour laquelle il ne faut pas utiliser d'autres langues?
FUZxxl
3
Si une solution est moins intéressante, ne votez pas. Interdire des solutions "boiteuses" en excluant des langues est exagéré.
FUZxxl
2
Si vous avez déjà limité le jeu de caractères à ASCII (ce que je considère absolument correct), comment pourrions-nous utiliser les hacks Unicode? En ce qui concerne la base 64, vous pouvez le faire à l'intérieur du standard C ainsi que dans tout autre langage, il ne s'agit que de différentes quantités de code wrapper. - Mais j'aime la tâche.
cessé de tourner dans le sens inverse des aiguilles d'une montre
1
Hmm, qu'en est-il des caractères de contrôle ASCII 0-31 (et 127)? Techniquement, ils font partie de l'ASCII, mais sont-ils autorisés? Et sinon, j'espère qu'une exception est au moins faite pour le caractère LF (10), et peut-être CR (13) et TAB (9) aussi?
Ilmari Karonen
1
Euh ... donc, en lisant votre nouvelle version littéralement, toutes les solutions doivent être sur une seule ligne, car les sauts de ligne non échappés ne sont pas autorisés. C'est vraiment ce que tu veux?
Ilmari Karonen

Réponses:

6

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

Journal des modifications:

  • 754-> 712: Ajouté returnau #define, remplaçant ifpar des ?instructions (merci @FUZxxl), supprimant intde la liste des paramètres des fonctions.
  • 712-> 703: copie sans vergogne de bunnit à nouveau :) Déplacé la création d'image entière dans le #define
  • 703-> 692: fusionné p[]et h[]quelques ?:améliorations supplémentaires
  • 692-> 685: Incrémentation bdonc iest plus nécessaire. m=bau lieu de m=11et n<2e3au lieu de i<356- ceux-ci sont proches d'une corruption de comportement / mémoire non définie, mais il semble que j'ai de la chance :)
  • 685-> 682: kest maintenant (32,16,8,4,2,1,0) au lieu de (5,4,3,2,1,0). Gotcha, DC;)
  • 682-> 670: Split p[]et h[], converti h[]en char*- awwww, il y a un minou endormi dedans^<+_=>-
  • 670-> 666: while=> for, l=l*2+...=>l+=l+...
  • 666-> 662: m=m>9?...=>c[n++]=m>9?...
  • 662-> 656: Ordre des bits inversé b[], nous pouvons donc mapper sur 64-127 au lieu de 0-63 et nous n'avons plus besoin d'index de bits k. Merci @Piotr Tarsa . Remplacé ?:(extension GCC) par ||. Merci @JamesB
  • 656-> 648: copie sans vergogne de Shelwien :) (constantes multi-caractères pour p[])

L'image est convertie en une chaîne de type Base64 (ASCII 37-100), en utilisant le codage Huffman pour coder les couleurs 0-9 en utilisant 3-6 bits et une couleur spéciale 10 (le pixel est le même que le précédent) en utilisant seulement 1 bit.

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

Copié deux choses de la réponse de bunnit, #defineet l'image entière étant décodée complètement à chaque appel de red/ green/ blue. Il y a de la place pour des améliorations supplémentaires, alors attendez-vous à quelques mises à jour :) Je ne suis pas sûr de la conformité du code, j'ai utilisé GCC 4.6.1 pour compiler et tester.

En ce qui concerne la compression, je pense que le codage arithmétique serait utile car la distribution est assez asymétrique, mais peut-être que la surcharge de code serait trop lourde dans ce cas. LZW devrait également faire un très bon travail. Les couleurs sont assez locales, donc le codage adaptatif pourrait être une idée.

Version 754 caractères plus lisible avec quelques commentaires:

#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
la source
Très bien, je ne peux pas croire que je n'ai pas pensé à utiliser la base 64. Je pense que vous pouvez quand même enregistrer pas mal de caractères, surtout dans cette boucle. Fonctionne bien dans VS2008 btw.
Scott Logan
Je pense que vous pouvez supprimer cela intdes listes de paramètres pour supprimer quelques octets supplémentaires.
FUZxxl
Et m=m>9?c[n-1]:m;pour if(m>9)m=c[n-1];?
FUZxxl
Et aussi: if(k<0){j=b[i++]-37;k=5;}pourquoi pas k>=0?:(j=b[i++]-37,k=5);? (Ce code utilise une extension C de gcc, x=a?:best le même que x=a?a:b, à la différence
près
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 caractères)

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]

Puisque ce défi est désormais ouvert à tous, pourquoi pas! C'est la route de codage familière zlib -> base64, donc je m'en excuse. Espérons qu'une entrée avec un semblant d'ingéniosité sera plus courte!

Voici un extrait de test analogue à l'original:

for y in range(32):
    for x in range(32):
        print red(x,y), blue(x,y), green(x,y)
Dillon Cower
la source
Vous devriez également essayer d'ajouter une couleur spéciale pour répéter la valeur de pixel précédente. 588 caractères base64 est beaucoup plus grand que la chaîne dans ma réponse (365 caractères) et bien que zLib soit exagéré ici, il devrait donner un résultat similaire, donc environ 500 caractères au total devraient être possibles de cette façon.
schnaader
4

C ++, 631 caractères; C - 613

Un codeur mtf unaire base-92, C ++, 631 caractères:

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

Et la version C ci-dessus (613 caractères):

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

Juste pour inclure une entrée avec des données de base 95 et un codage arithmétique + un modèle statistique adaptatif.
Le code de schnaader utilise environ 438 caractères pour les données et le mien seulement 318 (311 sans masquage).
Mais comme prévu, le codage arithmétique est trop compliqué pour un petit échantillon comme celui-ci.

(Il s'agit de 844 caractères)

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 (à partir d'une version antérieure de la base 96):
http://codepad.org/qrwuV3Oy
http://ideone.com/ATngC

D'une manière ou d'une autre, SO mange des codes 7F, j'ai donc dû le mettre à jour en base = 95

Shelwien
la source
3

C ++ - 1525 1004 964 caractères

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

Création d'un tableau z qui stocke toutes les couleurs possibles sous la forme d'un seul entier (r << 16 | g << 8 | b). Création d'un tableau d qui stocke {montant, valeur}, la valeur est la position dans le tableau z, le montant est le nombre de pixels consécutifs avec cette valeur (c'est-à-dire 3,0, signifie que colout t [0] apparaît les 3 suivants pixels. Le tableau réel de pixels (c) est ensuite calculé chaque fois que le rouge est appelé. La valeur dans le tableau est ensuite décalée vers la droite et modifiée si nécessaire pour obtenir le composant correct.

Je pourrais probablement enregistrer quelques caractères de plus (~ 50) en retirant plus de modèles du tableau tel que défini.

Edit 1 - a changé le tableau d pour un tableau char avec chaque valeur décalée de 48, ce qui signifie que je peux le représenter comme une chaîne enregistrant une charge de virgules.

Edit 2 - Suppression d'une plus grande partie des fonctions dans l'instruction define.

Scott Logan
la source
Pourquoi n'utilisez-vous pas C? En C, il est possible de supprimer le nom de type d'une déclaration s'il l'est int( int f(int x,int y)devient ainsi f(x,y).
FUZxxl
@FUzxxl, oui C sera presque toujours plus court que C ++ mais je n'utilise pas vraiment C au jour le jour et je ne connais pas vraiment toutes ses nuances qui peuvent être utilisées pour réduire la longueur. Je ne suis pas gêné en essayant de gagner de toute façon, j'essaie juste de battre toutes les autres réponses C ++.
Scott Logan
3

Javascript, 696 694 caractères

Merci à schnaader pour 696 -> 694.

J'ai figuré un format de codage différent, qui est essentiellement un codage de longueur avec une table de recherche de couleurs. Cela fonctionne assez bien, car il y a moins de 16 couleurs et elles apparaissent moins de 16 fois de suite; de sorte que chaque définition de pixel, y compris la longueur, tient dans un octet. J'ai mis la couleur dans la partie haute de l'octet et le nombre dans la partie basse.

Au final, la chaîne base64 s'est avérée plus longue que ce à quoi je m'attendais (472 caractères), mais le programme de décodage est vraiment court.

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)

Remarque: J'ai divisé le code pour avoir un peu de lisibilité. Il doit être sur une seule ligne pour fonctionner.

Code de test:

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

Je pense que l'exemple de résultat est en fait la sortie de rouge, vert, bleu (pas rouge, bleu, vert comme dans le code de test d'origine); ça marche pour moi comme ça de toute façon.

copie
la source
Essayez de changer le tableau de palettes en [0,16354410,4671418,6379596,7783255,5295994,5390379,3435360,9975021,5131894]- cela enregistre 1 caractère et correspond à l'ordre GBR au lieu de RGB.
schnaader
@schnaader Merci. J'adore ces micro-optimisations :-) Edit: Il a même enregistré 2 caractères car j'ai utilisé le bleu deux fois dans ma source d'origine
copie
2

C ++, 1357 caractères

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]

Désobfusqué un peu:

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]

Ccontient les valeurs RVB pour les dix couleurs distinctes de l'image. Econtient les données de l'image, où chaque élément E[i]code à la fois un nombre de répétitions E[i]/10et un indice de couleur E[i]%10.

Keith Randall
la source
+1 Vous pouvez raser quelques personnages dans la boucle: pastebin.com/2UY8H2qt
Pubby
1
Si vous renommez votre solution en C (aucun changement de code requis) et ne transformez les définitions en fonctions sans noms de type comme int red(x,y){R Q(x+32*y)[0]}(only # define` return), vous pourrez peut-être raser plus de caractères.
FUZxxl
1
D'une certaine manière, c'est de la triche, car le rouge, le bleu et le vert ne sont pas des fonctions mais des macros.
FUZxxl
1
Cela implémente une fonction et est plus court (1339 octets). Veuillez noter que ce programme n'est probablement valable que dans l'ancien C: hpaste.org/65584
FUZxxl
J'ai supprimé toutes les informations de type de la source. Il est toujours valide C.
FUZxxl
1

Python 3 (589 caractères)

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))

Code de test

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

Basé sur la solution de Dillon Cower

AMK
la source
1

PHP (5,4) - 822

J'ai fait cela délibérément en n'utilisant aucune des fonctions de compression intégrées . Cette solution n'est pas terminée, je ne sais pas si j'ai abandonné, je peux voir des points à améliorer mais je ne trouve pas le temps / la volonté de refactoriser le tout pour le moment, donc je poste ce que je ont jusqu'à présent.

Newlines + commentaires à supprimer pour 822 octets.

// 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;}

Talon de test:

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

La compression des données d'image elle-même est assez bonne, mais les fonctions de récupération des valeurs RVB occupent 1/4 du code.

J'utilise un mécanisme d'encodage personnalisé en base70 +.

  1. Il y a 10 couleurs uniques
  2. Les couleurs ont des longueurs comprises entre 1 et 14 (12 utilisées).
  3. Il y a 120 combinaisons possibles.
  4. Il n'y a que 70 combinaisons uniques de tirage / couleur réellement utilisées.

Les données d'image codées font référence à l'index de tableau d'un RLE, qui à son tour indexe le tableau de couleurs. Je ne sais pas combien de frais généraux cela ajoute ou soustrait par rapport directement aux couleurs.

Sinon il y a 10 couleurs (0 à 9), les RLE sont stockés sous run_length * 10 + colour_index. Donner une plage d'encodages entre 10 et 145 sans expérimenter avec des optimisations basées sur l'ordre des couleurs. (c'est-à-dire que je pourrais faire la plage 19 à 140 en déplaçant les couleurs 0 à 5, 5 à 9 et 9 à 0 - mais cela peut avoir d'autres effets d'entraînement)

Une réponse précédente indique que leurs données codées sont de 472 octets. Mes données d'image codées sont de 352 octets, mais la carte RLE / couleur intermédiaire (qui n'est pas codée en binaire) est de 129 octets supplémentaires, ce qui met le total à 481. (ainsi que des frais généraux supplémentaires pour joindre les deux). Cependant, je soupçonne que ma méthode pourrait être mieux adaptée aux images plus grandes.

FAIRE:

  1. Examiner l'encodage binaire de la carte RLE
  2. Trouvez un moyen de réduire la taille des fonctions. globalest une chienne, mais ne peut pas accéder aux index des caractères sur les constantes.
  3. Expérimentez avec l'ordre des index de couleurs pour voir si la taille de la carte RLE peut être réduite avec des séries séquentielles de nombres plus longues
  4. Optimisations spécifiques potentielles à 64 bits de la carte des couleurs? (r0 << 56 | r1 << 48 | ...)?
  5. Expérimentez avec le RLE vertical pour voir s'il se traduit par un ensemble d'encodages plus compact.
  6. Encodage de zone?
Leigh
la source
1

C (gcc) , 602 octets

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

Essayez-le en ligne!

Fatigué

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
la source