Perl, 438291 karakter
Jeff Burdges'in DEFLATE sıkıştırmasını , Ventero'nun sıkıştırılmış Ruby kodunu ve JB'nin Lingua :: EN :: Numbers'ı kullanmasından esinlenerek , girişimi dekompresyon kodu dahil 291 karaktere (kuyu, bayt) kadar sıkıştırmayı başardım. Program yazdırılamayan bazı karakterler içerdiğinden, MIME Base64 biçiminde sağladım :
dXNlIENvbXByZXNzOjpabGliO2V2YWwgdW5jb21wcmVzcyAneNolkMFqAkEMhu8+RVgELdaIXmXB
S2/FFyhF4k7cHTqTsclMZd++M3pJvo+QH5JiDJ9exkKrj/PqXOKV1bod77qj9b2UeGBZ7w/bpd9s
3rCDruf3uWtwS3qS/vfROy0xsho+oWbB3d+b19YsJHWGhIHp5eQ8GzqSoWkk/xxHH36a24OkuT38
K21kNm77ND81BceCWtlgoBAq4NWrM7gpyzDhxGKQi+bA6NIfG5K4/mg0d0kgTwwdvi67JHVeKKyX
l3acoxnSDYZJveVIBnGGrIUh1BQYqZacIDKc5Gvpt1vEk3wT3EmzejcyeIGqTApZmRftR7BH3B8W
/5Aze7In
Programın kodunu çözmek için aşağıdaki yardımcı Perl betiğini kullanabilirsiniz:
use MIME::Base64;
print decode_base64 $_ while <>;
Çıkışı adlı bir dosyaya kaydedin 12days.plve ile çalıştırın perl -M5.01 12days.pl. Belirtildiği gibi, kodun çalışması için Lingua :: EN :: Numbers modülünün kurulu olması gerekir.
Merak ediyorsanız, kodun okunabilir kısmı şöyle görünür:
use Compress::Zlib;eval uncompress '...'
burada ...254 bayt RFC 1950 sıkıştırılmış Perl kodu anlamına gelir. Sıkıştırılmamış, kod 361 karakter uzunluğundadır ve şöyle görünür:
use Lingua'EN'Numbers"/e/";s==num2en(12-$i++)." "=e,y"." "for@n=qw=drummers.drumming pipers.piping lords.a.leaping ladies.dancing maids.a.milking swans.a.swimming geese.a.laying golden.rings calling.birds french.hens turtle.doves.and=;say"on the ".num2en_ordinal($_)." day of christmas my true love gave to me @n[$i--..@n]a partridge in a pear tree
"for 1..12
Bu kodu yazmak garip bir golf egzersizi türüydü: tekrarlamayı en üst düzeye çıkarmak ve kullanılan farklı karakter sayısını en aza indirmek, ilgili metrik sıkıştırmadan sonra boyut olduğunda ham karakter sayısını en aza indirmekten çok daha önemlidir .
Son birkaç karakteri sıkıştırmak için, en iyi sıkıştırılanı bulmak için bu kodun küçük varyasyonlarını denemek için basit bir program yazdım. Sıkıştırma için, maksimum sıkıştırma ayarlarında bile standart Zlib'den daha iyi sıkıştırma oranları (hız maliyetiyle) veren Ken Silverman'ın KZIP yardımcı programını kullandım . Tabii ki, KZIP sadece ZIP arşivleri oluşturduğundan, ham DEFLATE akışını arşivden çıkarmak ve bir RFC 1950 üstbilgisi ve sağlama toplamına sarmak zorunda kaldım. İşte bunun için kullandığım kod:
use Compress::Zlib;
use 5.010;
@c = qw(e i n s);
@q = qw( " );
@p = qw( = @ ; , );
@n = ('\n',"\n");
$best = 999;
for$A(qw(e n .)){ for$B(@q){ for$C(@q,@p){ for$D(@p){ for$E(@q,@p){ for$F(qw(- _ . N E)){ for$G("-","-"eq$F?():$F){ for$H(@c){ for$I(@c,@p){ for$N(@n){ for$X(11,"\@$I"){ for$Y('$"','" "',$F=~/\w/?$F:()){ for$Z('".num2en_ordinal($_)."'){
$M="Lingua'EN'Numbers";
$code = q!use MB/A/B;sDDnum2en(12-$H++).YDe,yCFC Cfor@I=qwEdrummersFdrumming pipersFpiping lordsGaGleaping ladiesFdancing maidsGaGmilking swansGaGswimming geeseGaGlaying goldenFrings callingFbirds frenchFhens turtleFdovesFandE;say"on the Z day of christmas my true love gave to me @I[$H--..X]a partridge in a pear treeN"for 1..12!.$/;
$code =~ s/[A-Z]/${$&}/g;
open PL, ">12days.pl" and print PL $code and close PL or die $!;
$output = `kzipmix-20091108-linux/kzip -b0 -y 12days.pl.zip 12days.pl`;
($len) = ($output =~ /KSflating\s+(\d\d\d)/) or die $output;
open ZIP, "<12days.pl.zip" and $zip = join("", <ZIP>) and close ZIP or die $!;
($dfl) = ($zip =~ /12days\.pl(.{$len})/s) or die "Z $len: $code";
$dfl = "x\xDA$dfl" . pack N, adler32($code);
$dfl =~ s/\\(?=[\\'])|'/\\$&/g;
next if $best <= length $dfl;
$best = length $dfl;
$bestcode = $code;
warn "$A$B$C$D$E$F$G$H$I $X $Y $best: $bestcode\n";
open PL, ">12days_best.pl" and print PL "use Compress::Zlib;eval uncompress '$dfl'" and close PL or die $!;
}}}}}}
print STDERR "$A$B$C$D$E$F\r";
}}}}}}}
Bu korkunç bir kluge gibi görünüyorsa, bunun nedeni tam olarak budur.
Tarihsel ilgi için, satır sonları ve noktalama işaretleri de dahil olmak üzere daha güzel çıktı üreten orijinal 438 karakterlik çözümüm:
y/_/ /,s/G/ing/for@l=qw(twelve_drummers_drummG eleven_pipers_pipG ten_lords-a-leapG nine_ladies_dancG eight_maids-a-milkG seven_swans-a-swimmG six_geese-a-layG five_golden_rGs four_callG_birds three_french_hens two_turtle_doves);s/e?t? .*/th/,s/vt/ft/for@n=@l;@n[9..11]=qw(third second first);say map("\u$_,\n","\nOn the $n[11-$_] day of Christmas,\nMy true love gave to me",@l[-$_..-1]),$_?"And a":A," partridge in a pear tree."for 0..11
Bu sürümün s/e?t? .*/th/,s/vt/ft/, hediye hatlarının başlangıcında kardinallerden 4 ila 12 arasında sıra sıralarını oluşturan regexps çiftini vurgular .
Bu kod, elbette, yukarıda açıklanan Zlib hilesi kullanılarak da sıkıştırılabilir, ancak çıktıyı sıkıştırmanın daha verimli olduğu ve aşağıdaki 338 baytlık programı (yine Base64 formatında) sağladığı ortaya çıkar :
dXNlIENvbXByZXNzOjpabGliO3NheSB1bmNvbXByZXNzICd42uWTwU7DMAyG730KP8DGOyA0bsCB
vYBp3MYicSo7W9e3xx3ijCIQDHZIUjn683+/k3ZPAjUSDKxWIeACZYC7qGw1o226hwWqHghSORKM
6FMtkGnT3cKEWpXDSMACCBOhQlWim+7jUKO+SGg5dT8XqAetiSD4nrmPBMDPvXywtllF18OgJH2E
SGJfcR+Ky2KL/b0roMeUWEZ4cXb7biQeGol4LZQUSECdyn4A0vjUBvnMXCcYiYy2uE24ONcvgdOR
pBF9lYDNKObwNnPOTnc5kYjH2JZotyogI4c1Ueb06myXH1S48eYeWbyKgclcJr2D/dnwtfXZ7km8
qOeUiXBysP/VEUrt//LurIGJXCdSWxeHu4JW1ZnS0Ph8XOKloIecSe39w/murYdvbRU+Qyc=
Aynı DEFLATE akışından oluşturulan 312 baytlık bir gzip şarkı sözleri arşivim var. Sanırım buna "zcat betiği" diyebilirsiniz. :)