Perl, 438 291 ตัวอักษร
แรงบันดาลใจจากการใช้เจฟฟ์ Burdges ของการบีบอัดยุบ , Ventero ของการบีบอัดรหัสทับทิมและใช้ JB ของ Lingua :: EN :: เบอร์ฉันจัดการเพื่อบีบอัดรายการของฉันลงไป 291 ตัวอักษร (ดีไบต์) รวมทั้งรหัสการบีบอัด เนื่องจากโปรแกรมมีอักขระที่ไม่สามารถพิมพ์ได้บางตัวเราจึงได้จัดให้ในรูปแบบ MIME Base64 :
dXNlIENvbXByZXNzOjpabGliO2V2YWwgdW5jb21wcmVzcyAneNolkMFqAkEMhu8+RVgELdaIXmXB
S2/FFyhF4k7cHTqTsclMZd++M3pJvo+QH5JiDJ9exkKrj/PqXOKV1bod77qj9b2UeGBZ7w/bpd9s
3rCDruf3uWtwS3qS/vfROy0xsho+oWbB3d+b19YsJHWGhIHp5eQ8GzqSoWkk/xxHH36a24OkuT38
K21kNm77ND81BceCWtlgoBAq4NWrM7gpyzDhxGKQi+bA6NIfG5K4/mg0d0kgTwwdvi67JHVeKKyX
l3acoxnSDYZJveVIBnGGrIUh1BQYqZacIDKc5Gvpt1vEk3wT3EmzejcyeIGqTApZmRftR7BH3B8W
/5Aze7In
เพื่อยกเลิกการเข้ารหัสโปรแกรมคุณสามารถใช้สคริปต์ผู้ช่วยเหลือ Perl ต่อไปนี้:
use MIME::Base64;
print decode_base64 $_ while <>;
บันทึกการส่งออกในแฟ้มที่มีชื่อและเรียกมันด้วย12days.pl
perl -M5.01 12days.pl
ตามที่ระบุไว้คุณจะต้องมีLingua :: EN :: ตัวเลขโมดูลติดตั้งเพื่อให้โค้ดทำงานได้
ในกรณีที่คุณสงสัยส่วนที่อ่านได้ของโค้ดจะมีลักษณะดังนี้:
use Compress::Zlib;eval uncompress '...'
ที่...
หมายถึง 254 ไบต์ของRFC 1950รหัส Perl ที่ถูกบีบอัด ไม่บีบอัดรหัสมีความยาว 361 ตัวอักษรและมีลักษณะดังนี้:
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
การเขียนรหัสนี้เป็นแบบฝึกหัดการเล่นกอล์ฟแปลก ๆ : มันเป็นการเพิ่มการทำซ้ำให้มากที่สุดและการลดจำนวนตัวอักษรที่ใช้ให้ชัดเจนนั้นมีความสำคัญมากกว่าการลดจำนวนตัวอักษรดิบเมื่อตัวชี้วัดที่เกี่ยวข้องมีขนาด หลังจากการบีบอัดหลังจากการบีบอัด
ในการบีบตัวอักษรสองสามตัวที่ผ่านมาออกมาฉันได้เขียนโปรแกรมง่าย ๆ เพื่อลองใช้โค๊ดเล็ก ๆ ของโค้ดนี้เพื่อหาตัวที่ดีที่สุด สำหรับการบีบอัดฉันใช้KZIPยูทิลิตี้ของ Ken Silverman ซึ่งโดยปกติจะให้อัตราส่วนการบีบอัดที่ดีกว่า (ที่ราคาความเร็ว) กว่า Zlib มาตรฐานแม้ที่การตั้งค่าการบีบอัดสูงสุด แน่นอนเนื่องจาก KZIP สร้างเพียงไฟล์เก็บถาวร ZIP ฉันจึงต้องแยกสตรีม DEFLATE ดิบออกจากไฟล์เก็บถาวรและใส่ไว้ในส่วนหัวและการตรวจสอบ RFC 1950 นี่คือรหัสที่ฉันใช้:
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";
}}}}}}}
หากสิ่งนี้ดูเหมือนว่าจะเป็น kluge ที่น่ากลัวนั่นเป็นเพราะนั่นคือสิ่งที่มันเป็น
เพื่อความสนใจในอดีตนี่คือโซลูชัน 438-char ดั้งเดิมของฉันซึ่งสร้างเอาต์พุตที่ดีกว่ารวมถึงตัวแบ่งบรรทัดและเครื่องหมายวรรคตอน:
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
จุดเด่นของรุ่นนี้คือคู่ของ regexps s/e?t? .*/th/,s/vt/ft/
ซึ่งสร้างกฎสำหรับ 4 ถึง 12 จากพระคาร์ดินัลที่จุดเริ่มต้นของสายของขวัญ
แน่นอนว่ารหัสนี้สามารถบีบอัดได้โดยใช้ Zlib trick ที่อธิบายไว้ข้างต้น แต่ปรากฎว่าการบีบอัดเอาต์พุตมีประสิทธิภาพมากขึ้นโดยให้โปรแกรม 338- ไบต์ต่อไปนี้ (ในรูปแบบ Base64 อีกครั้ง):
dXNlIENvbXByZXNzOjpabGliO3NheSB1bmNvbXByZXNzICd42uWTwU7DMAyG730KP8DGOyA0bsCB
vYBp3MYicSo7W9e3xx3ijCIQDHZIUjn683+/k3ZPAjUSDKxWIeACZYC7qGw1o226hwWqHghSORKM
6FMtkGnT3cKEWpXDSMACCBOhQlWim+7jUKO+SGg5dT8XqAetiSD4nrmPBMDPvXywtllF18OgJH2E
SGJfcR+Ky2KL/b0roMeUWEZ4cXb7biQeGol4LZQUSECdyn4A0vjUBvnMXCcYiYy2uE24ONcvgdOR
pBF9lYDNKObwNnPOTnc5kYjH2JZotyogI4c1Ueb06myXH1S48eYeWbyKgclcJr2D/dnwtfXZ7km8
qOeUiXBysP/VEUrt//LurIGJXCdSWxeHu4JW1ZnS0Ph8XOKloIecSe39w/murYdvbRU+Qyc=
ฉันมีไฟล์เก็บถาวร gzip ขนาด 312 ไบต์ซึ่งสร้างจากสตรีม DEFLATE เดียวกัน ฉันคิดว่าคุณสามารถเรียกมันว่า "สคริปต์ zcat" :)