Codifique uma imagem dentro da fonte

10

O desafio do golfe é codificar e compactar a imagem a seguir dentro de um arquivo de origem.

Imagem

Para fazer isso você precisa escrever 3 funções: red, greene blueque aceitem x / y coordenadas da imagem e voltar a G / valor correspondente R / B pixels entre 0-255.

Aqui está o código de teste 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));
}

E a saída: http://pastebin.com/A770ckxL (você pode usar isso para gerar seus dados de imagem)

Regras e detalhes:

  • Isto é um golf
  • Apenas o seu código / arquivo é jogado no golfe - o código de teste é separado
  • O conjunto de caracteres usado é ASCII, no entanto, caracteres de controle em cadeias só podem ser usados ​​se forem escapados (como '\ n' e '\ r' etc.)
  • Tudo deve estar contido na fonte - sem carregamento de arquivo
  • Sua saída deve corresponder à saída de exemplo. Isso significa compactação sem perdas.

Línguas:

O problema foi escrito com o C / C ++ em mente, mas estou removendo essas restrições. Com isso dito, ainda vou recomendar usá-los.

Pubby
fonte
4
Se não houver um motivo específico para fazer isso, a correção de uma pergunta em um idioma específico é altamente desencorajada. Qual é a razão pela qual não se deve usar outras línguas?
FUZxxl 18/03/12
3
Se uma solução for menos interessante, não a vote. Proibir soluções "coxas" excluindo idiomas é um exagero.
FUZxxl 18/03/12
2
Se você já limitou o conjunto de caracteres para ASCII (que considero absolutamente aceitável), como poderíamos usar os hacks Unicode? Quanto à base 64, você pode fazer isso dentro do padrão C, assim como em qualquer outro idioma, apenas quantidades diferentes de código de invólucro. - Mas eu gosto da tarefa.
deixou de girar contra-
11
Hmm, e os caracteres de controle ASCII 0-31 (e 127)? Tecnicamente, eles fazem parte do ASCII, mas são permitidos? E se não, espero que seja feita pelo menos uma exceção para o caractere LF (10), e talvez CR (13) e TAB (9) também?
Ilmari Karonen 19/03/12
11
Hum ... então, lendo sua nova versão literalmente, todas as soluções precisam estar em uma linha, porque feeds de linha sem escape não são permitidos. É isso mesmo o que você pretende?
Ilmari Karonen 19/03/12

Respostas:

6

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

Changelog:

  • 754-> 712: Adicionado returnao #define, substituindo ifpor ?instruções (obrigado @FUZxxl), removendo intda lista de parâmetros de funções.
  • 712-> 703: Cópia descarada do bunnit novamente :) Moveu toda a criação da imagem para o #define
  • 703-> 692: Mesclados p[]e h[], mais algumas ?:melhorias
  • 692-> 685: Incrementar b, inão é mais necessário. m=bem vez de m=11e em n<2e3vez de i<356- estes são quase um comportamento indefinido / corrupção de memória, mas parece que tenho sorte :)
  • 685-> 682: kagora é (32,16,8,4,2,1,0) em vez de (5,4,3,2,1,0). Gotcha, DC;)
  • 682-> 670: Dividir p[]e h[], convertido h[]em um char*- awwww, há um gatinho sonolento nele^<+_=>-
  • 670-> 666: while=> for, l=l*2+...=>l+=l+...
  • 666-> 662: m=m>9?...=>c[n++]=m>9?...
  • 662-> 656: ordem de bits invertida b[], para que possamos mapear para 64-127 em vez de 0-63 e não precisarmos mais de índice de bits k. Obrigado @Piotr Tarsa . Substituído ?:(extensão GCC) por ||. Obrigado @JamesB
  • 656-> 648: Cópia desavergonhada de Shelwien :) (constantes de vários caracteres para p[])

A imagem é convertida em uma sequência do tipo Base64 (ASCII 37-100), usando a codificação huffman para codificar as cores de 0 a 9 usando 3-6 bits e uma cor especial 10 (o pixel é igual ao anterior) usando apenas 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;}

Foram copiadas duas coisas da resposta do bunnit, #definee toda a imagem sendo decodificada completamente toda vez red/ green/ bluesão chamadas. Há espaço para melhorias adicionais, portanto, espere algumas atualizações :) Não tenho certeza sobre a conformidade do código, usei o GCC 4.6.1 para compilar e testar.

Em termos de compressão, acho que a codificação aritmética ajudaria, pois a distribuição é bastante distorcida, mas talvez a sobrecarga do código seja muito pesada nesse caso. O LZW também deve fazer um trabalho muito bom. As cores são bastante locais, portanto, a codificação adaptativa pode ser uma ideia.

Versão mais legível de 754 caracteres com alguns comentários:

#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
fonte
Muito bom, não acredito que não pensei em usar a base 64. Acho que você ainda pode salvar alguns caracteres, especialmente nesse loop. Funciona bem no VS2008 btw.
Scott Logan
Eu acho que você pode remover isso intdas listas de parâmetros para remover mais alguns bytes.
FUZxxl 22/03/12
Que tal m=m>9?c[n-1]:m;para if(m>9)m=c[n-1];?
FUZxxl 22/03/12
E também: por if(k<0){j=b[i++]-37;k=5;}que não k>=0?:(j=b[i++]-37,k=5);? (Este código utiliza uma extensão de C gcc, x=a?:bé o mesmo que x=a?a:b, com a diferença de que uma é avaliada apenas uma vez.
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 22/03/12
4

Python ( 684.592 caracteres)

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]

Como esse desafio está agora aberto a todos, por que não! É a rota de codificação familiar zlib -> base64, então peço desculpas por isso. Esperemos que uma entrada com alguma aparência de criatividade seja mais curta!

Aqui está um trecho de teste análogo ao original:

for y in range(32):
    for x in range(32):
        print red(x,y), blue(x,y), green(x,y)
Dillon Cower
fonte
Você deve tentar adicionar uma cor especial para repetir também o valor anterior do pixel. 588 caracteres base64 é muito maior que a string na minha resposta (365 caracteres) e, embora o zLib seja um exagero aqui, ele deve fornecer um resultado semelhante, portanto, cerca de 500 caracteres no total devem ser possíveis dessa maneira.
schnaader
4

C ++, 631 caracteres; C - 613

Um codificador mtf unificado base-92, C ++, 631 caracteres:

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

E a versão C acima (613 caracteres):

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

Apenas para incluir uma entrada com dados da base 95 e codificação aritmética + modelo estatístico adaptável.
o código do schnaader usa ~ 438 caracteres para dados e o meu apenas 318 (311 sem mascarar).
Mas, como esperado, a codificação aritmética é muito complicada para uma amostra pequena como essa.

(Este é 844 caracteres)

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)

Testes (da versão base-96 anterior):
http://codepad.org/qrwuV3Oy
http://ideone.com/ATngC

De alguma forma SO come códigos 7F, então eu tive que atualizá-lo para base = 95

Shelwien
fonte
3

C ++ - 1525 1004 964 caracteres

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

Criou uma matriz z que armazena todas as cores possíveis como um único número inteiro (r << 16 | g << 8 | b). Criou uma matriz d que armazena {quantidade, valor}, o valor é a posição na matriz z, a quantidade é o número de pixels consecutivos com esse valor (ou seja, 3,0, significa colout t [0] aparece nos próximos 3 A matriz real de pixels (c) é calculada toda vez que o vermelho é chamado.O valor na matriz é então deslocado para a direita e ANDed conforme necessário para obter o componente correto.

Provavelmente eu poderia salvar mais alguns caracteres (~ 50) retirando mais padrões da matriz, conforme definido.

Editar 1 - alterou a matriz d para uma matriz de caracteres com cada valor compensado por 48, o que significa que eu posso representá-la como uma sequência que economiza uma carga de vírgulas.

Editar 2 - Tirou uma parte maior das funções da instrução define.

Scott Logan
fonte
Por que você não usa C? Em C, é possível remover o nome do tipo de um declaratrion, se for int(o que int f(int x,int y)se torna f(x,y).)
FUZxxl
@FUzxxl, sim C quase sempre será menor que C ++, mas eu realmente não uso C no dia a dia e realmente não sei todas as nuances que podem ser usadas para reduzir o comprimento. Eu não estou incomodado tentando ganhar de qualquer maneira, apenas tento vencer quaisquer outras respostas em C ++.
Scott Logan
3

Javascript, 696 694 caracteres

Agradecimentos a schnaader por 696 -> 694.

Imaginei um formato de codificação diferente, que é essencialmente a codificação de execução com uma tabela de pesquisa de cores. Funciona bastante bem, porque há menos de 16 cores e elas aparecem menos que 16 vezes seguidas; portanto, cada definição de pixel, incluindo o comprimento, cabe em um byte. Coloquei a cor na parte alta do byte e a contagem na parte baixa.

No final, a string base64 acabou sendo mais longa do que eu esperava (472 caracteres), mas o programa de decodificação é realmente curto.

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)

Nota: Dividi o código para ter um pouco de legibilidade. Ele precisa estar em uma linha para executar.

Código do teste:

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

Eu acho que o resultado do exemplo é realmente a saída de vermelho, verde, azul (não vermelho, azul, verde, como no código de teste original); funciona para mim assim mesmo.

cópia de
fonte
Tente alterar a matriz da paleta para [0,16354410,4671418,6379596,7783255,5295994,5390379,3435360,9975021,5131894]- isso salva 1 caractere e é da ordem GBR em vez de RGB.
schnaader
@schnaader Obrigado. Eu amo essas micro-otimizações :-) Edit: Ele até salvou 2 caracteres porque eu usei azul duas vezes na minha fonte original
copie o
2

C ++, 1357 caracteres

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]

Desobstruído um pouco:

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]

Ccontém os valores RGB para as dez cores distintas da imagem. Econtém os dados da imagem, onde cada elemento E[i]codifica uma contagem de repetição E[i]/10e um índice de cores E[i]%10.

Keith Randall
fonte
+1 Você poderia raspar alguns personagens fora do loop: pastebin.com/2UY8H2qt
Pubby
11
Se você renomear sua solução como C (nenhuma alteração de código é necessária) e transformar as int red(x,y){R Q(x+32*y)[0]}(only definições em funções sem nomes de tipo como # define` return), poderá ser capaz de se barbear com mais caracteres.
FUZxxl 19/03/12
11
De alguma forma, isso é trapaça, pois vermelho, azul e verde não são funções, mas macros.
FUZxxl 19/03/12
11
Isso implementa uma função e é mais curto (1339 bytes). Observe que este programa provavelmente é válido apenas no antigo C: hpaste.org/65584
FUZxxl
Eu removi todas as informações de tipo da fonte. Ainda é C.
FUZxxl 19/03/12
1

Python 3 (589 caracteres)

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

Código de teste

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

Baseado na solução da Dillon Cower

AMK
fonte
1

PHP (5.4) - 822

Fiz isso deliberadamente sem usar nenhuma das funções de compactação internas . Esta solução não está concluída, não tenho certeza se desisti, posso ver áreas para melhoria, mas não encontro tempo / força de vontade para refatorar tudo no momento, por isso estou postando o que tem até agora.

Novas linhas + comentários a serem removidos por 822 bytes.

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

Esboço de teste:

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

A compactação dos dados da imagem em si é bastante boa, mas as funções para recuperar valores RGB ocupam 1/4 do código.

Estou usando um mecanismo de codificação base70 + personalizado.

  1. Existem 10 cores únicas
  2. As cores têm comprimentos entre 1 e 14 (12 usados).
  3. Existem 120 combinações possíveis.
  4. Existem apenas 70 combinações únicas de cor / corrida realmente usadas.

Os dados da imagem codificada referenciam o índice da matriz de um RLE, que por sua vez indexa a matriz de cores. Não tenho certeza de quanto isso sobrecarga adiciona ou subtrai diretamente sobre as cores.

Seno existem 10 cores (0 a 9), os RLEs são armazenados como run_length * 10 + colour_index. Fornecendo uma variedade de codificações entre 10 e 145 sem experimentar otimizações baseadas na ordem das cores. (ou seja, eu poderia fazer o intervalo de 19 a 140 movendo as cores de 0 a 5, 5 a 9 e 9 a 0 - mas isso pode ter outros efeitos indiretos)

Uma resposta anterior afirma que seus dados codificados são 472 bytes. Meus dados de imagem codificados são 352 bytes, mas o RLE intermediário / mapa de cores (que não é codificado em binário) tem mais 129 bytes, colocando o total em 481. (além de sobrecarga adicional para unir os dois). No entanto, suspeito que meu método possa ser melhor dimensionado para imagens maiores.

FAÇAM:

  1. Investigar a codificação binária do mapa RLE
  2. Encontre uma maneira de reduzir o tamanho das funções. globalé uma droga, mas não pode acessar índices de caracteres em constantes.
  3. Experimente fazer pedidos de índice de cores para verificar se o tamanho do mapa RLE pode ser reduzido com execuções sequenciais mais longas de números
  4. Potenciais otimizações específicas de 64 bits do mapa de cores? (r0 << 56 | r1 << 48 | ...)?
  5. Experimente o RLE vertical para ver se ele resulta em um conjunto mais compacto de codificações.
  6. Codificação de área?
Leigh
fonte
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)}

Experimente online!

Atropelar

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
fonte