Menyandikan gambar di dalam sumber


10

Tantangan golf adalah menyandikan dan mengompres gambar berikut di dalam file sumber.

Gambar

Untuk melakukan ini, Anda perlu menulis 3 fungsi: red,, greendan blueyang menerima koordinat x / y gambar dan mengembalikan nilai piksel R / G / B yang sesuai antara 0-255.

Berikut adalah kode uji 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));
}

Dan hasilnya: http://pastebin.com/A770ckxL (Anda dapat menggunakan ini untuk menghasilkan data gambar Anda)

Aturan & detail:

  • Ini golf
  • Hanya kode / file Anda yang di-golf - kode tes terpisah
  • Set karakter yang digunakan adalah ASCII, namun karakter kontrol dalam string hanya dapat digunakan jika lolos (seperti '\ n' dan '\ r', dll.)
  • Semuanya harus terkandung di dalam sumbernya - tanpa memuat file
  • Output Anda harus sesuai dengan contoh output. Ini berarti kompresi tanpa kehilangan.

Bahasa:

Masalahnya ditulis dengan C / C ++ dalam pikiran, tapi saya menghapus pembatasan itu. Dengan itu, saya masih akan merekomendasikan menggunakannya.


4
Jika tidak ada alasan khusus untuk melakukannya, memperbaiki pertanyaan ke bahasa tertentu sangat tidak dianjurkan. Apa alasannya mengapa seseorang tidak boleh menggunakan bahasa lain?
FUZxxl

3
Jika solusi kurang menarik, jangan pilih itu. Melarang solusi "lumpuh" dengan mengecualikan bahasa adalah berlebihan.
FUZxxl

2
Jika Anda sudah membatasi set karakter ke ASCII (yang saya anggap benar-benar ok), bagaimana kita bisa menggunakan peretasan Unicode? Sedangkan untuk base 64, Anda dapat melakukannya di dalam standar C dan juga bahasa lainnya, itu hanya jumlah kode pembungkus yang berbeda. - Tapi saya suka tugasnya.
Berhenti menghidupkan counterclock

1
Hmm, bagaimana dengan karakter kontrol ASCII 0-31 (dan 127)? Secara teknis, mereka bagian dari ASCII, tetapi apakah mereka diizinkan? Dan jika tidak, saya harap pengecualian setidaknya dibuat untuk karakter LF (10), dan mungkin CR (13) dan TAB (9) juga?
Ilmari Karonen

1
Um ... jadi, membaca versi baru Anda secara harfiah, semua solusi harus berada di satu baris, karena umpan baris yang tidak diblokir tidak diperbolehkan. Apakah itu yang Anda inginkan?
Ilmari Karonen

Jawaban:


6

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

Changelog:

  • 754-> 712: Ditambahkan returnke #define, diganti ifdengan ?pernyataan (terima kasih @FUZxxl), hapus intdari daftar parameter fungsi.
  • 712-> 703: Salin tak tahu malu dari kelinci lagi :) Pindahkan seluruh gambar ke dalam #define
  • 703-> 692: Digabung p[]dan h[], beberapa ?:peningkatan lagi
  • 692-> 685: Menambahkan bjadi itidak diperlukan lagi. m=bbukannya m=11dan n<2e3bukannya i<356- ini dekat dengan perilaku / memori rusak, tetapi sepertinya saya beruntung :)
  • 685-> 682: ksekarang (32,16,8,4,2,1,0) bukannya (5,4,3,2,1,0). Gotcha, DC;)
  • 682-> 670: Membelah p[]dan h[], dikonversi h[]menjadi char*- awwww, ada kucing mengantuk di dalamnya^<+_=>-
  • 670-> 666: while=> for, l=l*2+...=>l+=l+...
  • 666-> 662: m=m>9?...=>c[n++]=m>9?...
  • 662-> 656: Urutan bit terbalik b[], jadi kita dapat memetakan ke 64-127 alih-alih 0-63 dan tidak perlu indeks bit klagi. Terima kasih @Piotr Tarsa . Diganti ?:(ekstensi GCC) dengan ||. Terima kasih @JamesB
  • 656-> 648: Salinan tak tahu malu dari Shelwien :) (konstanta multi-karakter untuk p[])

Gambar dikonversi ke string seperti Base64 (ASCII 37-100), menggunakan huffman coding untuk mengkodekan warna 0-9 menggunakan 3-6 bit dan warna khusus 10 (pixel sama seperti sebelumnya) menggunakan hanya 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;}

Disalin dua hal dari jawaban bunnit, para #definedan seluruh gambar yang diterjemahkan sepenuhnya setiap kali red/ green/ bluedisebut. Ada beberapa ruang untuk perbaikan tambahan, jadi harapkan beberapa pembaruan :) Saya tidak yakin tentang kepatuhan kode, menggunakan GCC 4.6.1 untuk mengkompilasi dan menguji.

Dari segi kompresi, saya pikir pengkodean aritmatika akan membantu karena distribusinya cukup miring, tapi mungkin kode overhead akan terlalu berat dalam kasus ini. LZW juga harus melakukan pekerjaan dengan sangat baik. Warna cukup lokal, jadi pengkodean adaptif mungkin merupakan ide.

754 versi karakter yang lebih mudah dibaca dengan beberapa komentar:

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

Sangat bagus, tidak percaya saya tidak berpikir tentang menggunakan basis 64. Saya pikir Anda masih dapat menyimpan beberapa karakter, terutama di loop itu. Bekerja dengan baik di VS2008 btw.
Scott Logan

Saya pikir Anda dapat menghapus itu intdari daftar parameter untuk menghapus beberapa byte lagi.
FUZxxl

Bagaimana dengan m=m>9?c[n-1]:m;untuk if(m>9)m=c[n-1];?
FUZxxl

Dan juga: if(k<0){j=b[i++]-37;k=5;}mengapa tidak k>=0?:(j=b[i++]-37,k=5);? (Kode ini menggunakan ekstensi C dari gcc, x=a?:bsama dengan x=a?a:b, dengan perbedaan bahwa a hanya dievaluasi sekali.
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 karakter)

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]

Karena tantangan ini sekarang terbuka untuk semua, mengapa tidak! Ini adalah rute penyandian zlib -> base64 yang sudah dikenal, jadi saya minta maaf untuk itu. Semoga entri dengan sedikit kecerdikan akan lebih pendek!

Berikut cuplikan uji yang dianalogikan dengan aslinya:

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

Anda harus mencoba menambahkan warna khusus untuk mengulangi nilai piksel sebelumnya juga. 588 chars base64 jauh lebih besar daripada string dalam jawaban saya (365 chars) dan meskipun zLib berlebihan di sini, itu harus memberikan hasil yang sama, jadi sekitar 500 chars total harus dimungkinkan dengan cara ini.
schnaader

4

C ++, 631 karakter; C - 613

Coder mtf unary base-92, C ++, 631 karakter:

#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#B3BLMiI8@-Zo-EsgE.R#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;}

Dan versi C di atas (613 karakter):

#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#B3BLMiI8@-Zo-EsgE.R#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;}

Hanya untuk memasukkan entri dengan basis-95 data dan kode aritmatika + model statistik adaptif.
kode schnaader menggunakan ~ 438 karakter untuk data, dan hanya milikku 318 (311 tanpa topeng).
Tapi seperti yang diharapkan, pengkodean aritmatika terlalu rumit untuk sampel kecil seperti ini.

(Ini adalah 844 karakter)

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)

Pengujian (dari versi base-96 sebelumnya):
http://codepad.org/qrwuV3Oy
http://ideone.com/ATngC

Entah bagaimana SO makan kode 7F, jadi saya harus memperbaruinya ke base = 95


3

C ++ - 1525 1004 964 karakter

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

Membuat array z yang menyimpan semua warna yang mungkin sebagai bilangan bulat tunggal. (R << 16 | g << 8 | b). Membuat array d yang menyimpan {jumlah, nilai}, nilainya adalah posisi dalam array z, jumlahnya adalah jumlah piksel berturut-turut dengan nilai itu. (Yaitu 3,0, berarti colout t [0] muncul 3 berikutnya piksel. Array sebenarnya dari piksel (c) kemudian dihitung setiap kali merah disebut. Nilai dalam array kemudian bergeser ke kanan dan ANDed sesuai kebutuhan untuk mendapatkan komponen yang benar.

Saya mungkin bisa menyimpan beberapa karakter lagi (~ 50) dengan mengambil lebih banyak pola dari array sebagai definisi.

Sunting 1 - mengubah array d untuk array char dengan masing-masing nilai diimbangi oleh 48, yang berarti saya dapat menggambarkannya sebagai string yang menyimpan beban koma.

Sunting 2 - Mengambil sebagian besar fungsi di dalam pernyataan define.


Mengapa Anda tidak menggunakan C? Dalam C, adalah mungkin untuk menghapus jenis-nama dari declaratrion jika itu int(jadi int f(int x,int y)menjadi f(x,y).
FUZxxl

@ Fuzxxl, ya C akan hampir selalu lebih pendek dari C ++ tapi saya tidak benar-benar menggunakan C setiap hari dan tidak benar-benar tahu semua itu nuansa yang dapat digunakan untuk mengurangi panjangnya. Saya tidak terganggu dengan mencoba untuk menang, saya hanya mencoba untuk mengalahkan jawaban C ++ lainnya.
Scott Logan

3

Javascript, 696 694 karakter

Terima kasih kepada schnaader untuk 696 -> 694.

Saya menemukan format pengodean yang berbeda, yang pada dasarnya adalah pengodean Run-length dengan tabel pencarian warna. Ini bekerja cukup baik, karena ada kurang dari 16 warna dan mereka muncul kurang dari 16 kali berturut-turut; jadi setiap definisi piksel termasuk panjang cocok menjadi satu byte. Saya menempatkan warna di bagian tinggi byte dan hitungan di bagian rendah.

Pada akhirnya, string base64 ternyata lebih panjang dari yang saya duga (472 karakter), tetapi program penguraiannya sangat singkat.

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)

Catatan: Saya membagi kode untuk memiliki sedikit keterbacaan. Perlu berada di satu baris untuk menjalankan.

Kode uji:

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

Saya pikir contoh hasil sebenarnya adalah output dari merah, hijau, biru (bukan merah, biru, hijau seperti dalam kode tes asli); tetap bekerja untuk saya seperti itu.


Cobalah untuk mengubah array palet ke [0,16354410,4671418,6379596,7783255,5295994,5390379,3435360,9975021,5131894]- ini menghemat 1 karakter dan merupakan urutan GBR bukan RGB.
schnaader

@ schnaader Terima kasih. Saya suka optimasi mikro itu :-) Sunting: Ini bahkan menyelamatkan 2 karakter karena saya menggunakan biru dua kali di sumber orignial saya
salin

2

C ++, 1357 karakter

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]

Deobfuscated sedikit:

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]

Cberisi nilai RGB untuk sepuluh warna gambar yang berbeda. Eberisi data untuk gambar, di mana setiap elemen E[i]mengkodekan hitungan ulang E[i]/10dan indeks warna E[i]%10.


+1 Anda dapat mencukur beberapa karakter dalam loop: pastebin.com/2UY8H2qt
Pubby

1
Jika Anda mengubah nama solusi Anda sebagai C (tidak perlu perubahan kode) dan mengubah fungsi define menjadi tanpa nama tipe seperti int red(x,y){R Q(x+32*y)[0]}(only # define` return), maka Anda mungkin dapat mencukur lebih banyak karakter.
FUZxxl

1
Entah bagaimana, ini curang, karena merah, biru dan hijau bukan fungsi tetapi makro.
FUZxxl

1
Ini mengimplementasikan fungsi dan lebih pendek (1339 byte). Harap perhatikan, bahwa program ini mungkin hanya berlaku di C lama: hpaste.org/65584
FUZxxl

Saya menghapus semua jenis informasi dari sumbernya. Ini masih berlaku C.
FUZxxl

1

Python 3 (589 karakter)

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

Kode uji

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

Berdasarkan solusi dari Dillon Cower


1

PHP (5.4) - 822

Saya sudah melakukan ini dengan sengaja tidak menggunakan salah satu fungsi built-in kompresi . Solusi ini belum selesai, saya tidak yakin jika saya sudah menyerah, saya dapat melihat area untuk perbaikan tetapi saya tidak dapat menemukan waktu / kemauan untuk memperbaiki semuanya saat ini, jadi saya memposting apa yang saya miliki sejauh ini.

Baris baru + komentar akan dihapus untuk 822 byte.

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

Tes rintisan:

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

Kompresi data gambar itu sendiri cukup bagus, tetapi fungsi untuk mengambil nilai RGB membutuhkan 1/4 kode.

Saya menggunakan mekanisme encoding panjang base70 + run kustom.

  1. Ada 10 warna unik
  2. Warna memiliki panjang lari antara 1 dan 14 (12 digunakan).
  3. Ada 120 kemungkinan kombinasi.
  4. Hanya ada 70 kombinasi run / warna unik yang benar-benar digunakan.

Data gambar yang disandikan referensi indeks array dari RLE, yang pada gilirannya indeks array warna. Saya tidak yakin berapa banyak overhead ini menambah atau mengurangi secara langsung referensi warna.

Karena ada 10 warna (0 hingga 9), RLE disimpan sebagai run_length * 10 + colour_index. Memberikan serangkaian penyandian antara 10 dan 145 tanpa bereksperimen dengan optimisasi berdasarkan pemesanan warna. (yaitu saya dapat membuat kisaran 19 hingga 140 dengan memindahkan warna 0 hingga 5, 5 hingga 9, dan 9 hingga 0 - tetapi ini mungkin memiliki efek ketukan lainnya)

Jawaban sebelumnya menyatakan data yang dikodekan adalah 472 byte. Data gambar saya yang disandikan adalah 352 byte, tetapi RLE / peta warna menengah (yang bukan disandikan biner) adalah 129 byte lebih lanjut, sehingga totalnya adalah 481. (serta overhead tambahan untuk menggabungkan keduanya). Namun saya menduga metode saya mungkin skala yang lebih baik untuk gambar yang lebih besar.

MELAKUKAN:

  1. Selidiki penyandian biner dari peta RLE
  2. Temukan cara mengurangi ukuran fungsi. globaladalah menyebalkan, tetapi tidak dapat mengakses indeks karakter pada konstanta.
  3. Lakukan percobaan dengan pemesanan indeks warna untuk melihat apakah ukuran peta RLE dapat dikurangi dengan angka berurutan yang lebih panjang
  4. Potensi optimasi 64bit spesifik dari peta warna? (r0 << 56 | r1 << 48 | ...)?
  5. Percobaan dengan RLE vertikal untuk melihat apakah itu menghasilkan serangkaian pengkodean yang lebih kompak.
  6. Pengkodean area?

1

C (gcc) , 602 byte

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

Cobalah online!

Kehabisan

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)}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.