Perl, 438 291 Zeichen
Inspiriert von Jeff Burdges 'DEFLATE-Komprimierung , Venteros komprimiertem Ruby-Code und JBs Lingua :: EN :: Numbers gelang es mir, meine Eingabe auf 291 Zeichen (naja, Bytes) einschließlich Dekomprimierungscode zu komprimieren. Da das Programm einige nicht druckbare Zeichen enthält, habe ich es im MIME Base64-Format bereitgestellt :
dXNlIENvbXByZXNzOjpabGliO2V2YWwgdW5jb21wcmVzcyAneNolkMFqAkEMhu8+RVgELdaIXmXB
S2/FFyhF4k7cHTqTsclMZd++M3pJvo+QH5JiDJ9exkKrj/PqXOKV1bod77qj9b2UeGBZ7w/bpd9s
3rCDruf3uWtwS3qS/vfROy0xsho+oWbB3d+b19YsJHWGhIHp5eQ8GzqSoWkk/xxHH36a24OkuT38
K21kNm77ND81BceCWtlgoBAq4NWrM7gpyzDhxGKQi+bA6NIfG5K4/mg0d0kgTwwdvi67JHVeKKyX
l3acoxnSDYZJveVIBnGGrIUh1BQYqZacIDKc5Gvpt1vEk3wT3EmzejcyeIGqTApZmRftR7BH3B8W
/5Aze7In
Um das Programm zu entschlüsseln, können Sie das folgende Hilfs-Perl-Skript verwenden:
use MIME::Base64;
print decode_base64 $_ while <>;
Speichern Sie die Ausgabe in einer Datei mit dem Namen 12days.pl
und führen Sie sie mit aus perl -M5.01 12days.pl
. Wie bereits erwähnt, muss das Lingua :: EN :: Numbers- Modul installiert sein, damit der Code funktioniert.
Falls Sie sich fragen, sieht der lesbare Teil des Codes einfach so aus:
use Compress::Zlib;eval uncompress '...'
Dabei ...
steht das für 254 Bytes RFC 1950- komprimierten Perl-Code. Unkomprimiert ist der Code 361 Zeichen lang und sieht folgendermaßen aus:
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
Das Schreiben dieses Codes war eine seltsame Art von Golfübung: Es stellte sich heraus, dass die Maximierung der Wiederholung und die Minimierung der Anzahl der verwendeten unterschiedlichen Zeichen viel wichtiger sind als die Minimierung der Anzahl der rohen Zeichen, wenn die relevante Metrik die Größe nach der Komprimierung ist .
Um die letzten Zeichen herauszufiltern, habe ich ein einfaches Programm geschrieben, um kleine Variationen dieses Codes auszuprobieren und das zu finden, das am besten komprimiert. Für die Komprimierung habe ich Ken Silvermans KZIP- Dienstprogramm verwendet, das in der Regel selbst bei maximalen Komprimierungseinstellungen bessere Komprimierungsraten (auf Kosten der Geschwindigkeit) liefert als Standard-Zlib. Da KZIP nur ZIP-Archive erstellt, musste ich natürlich den unformatierten DEFLATE-Stream aus dem Archiv extrahieren und ihn in einen RFC 1950-Header und eine Prüfsumme verpacken. Hier ist der Code, den ich dafür verwendet habe:
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";
}}}}}}}
Wenn das wie ein schrecklicher Schlitten aussieht, dann ist es genau das, was es ist.
Aus historischen Gründen ist hier meine ursprüngliche 438-Zeichen-Lösung, die eine bessere Ausgabe, einschließlich Zeilenumbrüchen und Interpunktion, generiert:
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
Höhepunkte dieser Version sind die beiden Regexps s/e?t? .*/th/,s/vt/ft/
, die aus den Kardinälen am Anfang der Geschenklinien die Ordnungszahlen für 4 bis 12 bilden.
Dieser Code kann natürlich auch mit dem oben beschriebenen Zlib-Trick komprimiert werden, aber es stellt sich heraus, dass das einfache Komprimieren der Ausgabe effizienter ist und das folgende 338-Byte-Programm ergibt (wieder im Base64-Format):
dXNlIENvbXByZXNzOjpabGliO3NheSB1bmNvbXByZXNzICd42uWTwU7DMAyG730KP8DGOyA0bsCB
vYBp3MYicSo7W9e3xx3ijCIQDHZIUjn683+/k3ZPAjUSDKxWIeACZYC7qGw1o226hwWqHghSORKM
6FMtkGnT3cKEWpXDSMACCBOhQlWim+7jUKO+SGg5dT8XqAetiSD4nrmPBMDPvXywtllF18OgJH2E
SGJfcR+Ky2KL/b0roMeUWEZ4cXb7biQeGol4LZQUSECdyn4A0vjUBvnMXCcYiYy2uE24ONcvgdOR
pBF9lYDNKObwNnPOTnc5kYjH2JZotyogI4c1Ueb06myXH1S48eYeWbyKgclcJr2D/dnwtfXZ7km8
qOeUiXBysP/VEUrt//LurIGJXCdSWxeHu4JW1ZnS0Ph8XOKloIecSe39w/murYdvbRU+Qyc=
Ich habe auch ein 312-Byte-GZIP-Archiv mit den Texten, das aus demselben DEFLATE-Stream erstellt wurde. Ich nehme an, Sie könnten es ein "zcat-Skript" nennen. :)