views:

4757

answers:

46

Print all 12 verses of the popular holiday song.

By 12 verses I mean the repetition of each line as is sung in the song, ie

Verse One: On the first day of Christmas my true love gave to me a partridge in a pear tree.

Verse Two On the second day of Christmas my true love gave to me two turtle doves and a partridge in a pear tree.

...

Verse N: On the nth day of Christmas my true love gave to me (Verse N-1 without the first line) (line added in verse N)

+43  A: 

Common Lisp:

(mapc #'princ
      (reverse (maplist #'(lambda(l)
      (format nil 
            "On the ~:R day of Christmas my true love gave to me~%~{~a~%~}~%" 
                (length l) l)) 
 '("twelve drummers drumming,"
   "eleven pipers piping,"
   "ten lords a-leaping,"
   "nine ladies dancing,"
   "eight maids a-milking,"
   "seven swans a-swimming,"
   "six geese a-laying,"
   "five gold rings,"
   "four calling birds,"
   "three french hens,"
   "two turtle doves, and"
   "a partridge in a pear tree."))))

Edit:

Above is 412 characters if you take out the whitespace.

This one:

(let ((g))
  (dotimes (i 12)
    (format t
        "On the ~:R day of Christmas my true love gave to me~%~{~R ~:*~
         ~[~;~;turtle doves and~;french hens,~;calling birds,~;gold rings,~
         ~;geese a-laying,~;swans a-swimming,~;maids a-milking,~
         ~;ladies dancing,~;lords a-leaping,~;pipers piping,~
         ~;drummers drumming,~]~%~}a partridge in a pear tree~2%"
        (1+ i) g)
    (push (+ i 2) g)))

is 344 characters if you take out whitespace and ~ quoted newlines in the format string:

(let((g))(dotimes(i 12)(format t"On the ~:R day of Christmas my true love gave to me~%~{~R ~:*~[~;~;turtle doves and~;french hens,~;calling birds,~;gold rings,~;geese a-laying,~;swans a-swimming,~;maids a-milking,~;ladies dancing,~;lords a-leaping,~;pipers piping,~;drummers drumming,~]~%~}a partridge in a pear tree~2%"(1+ i)g)(push(+ i 2)g)))

Edit:

It looks like the question has run its course, and the site is nagging me to accept an answer. As far as I can see, this one is the shortest. I'm a little afraid of what the site will do if I accept my own answer - probably award me a Narcissist or Masturbator badge.

You can't accept your own answers. Fair enough. I'll leave it open. Thanks to everyone who responded.

fizzer
There will be a smart way to get rid of the cardinals with ~R, but it escapes me at the moment
fizzer
What a language...
Frank Krueger
You have a typo on day 8. "eigth" should be "eight".
Matthew Crumley
Since when does lisp come with a perl interpreter?
Jasper Bekkers
its ok to accept your own answers, you just don't get reputation for it.
Jimmy
+3  A: 

C#:

string[] s = new string[]{
    "a partridge in a pear tree.",
    "two turtle doves, and ",
    "three french hens, ",
    "four calling birds, ",
    "five gold rings, ",
    "six geese a-laying, ",
    "seven swans a-swimming, ",
    "eight maids a-milking, ",
    "nine ladies dancing, ",
    "ten lords a-leaping, ",
    "eleven pipers piping, ",
    "twelve drummers drumming, "
    };
string t = "";
for (int x = 0; x < s.Length; x++) {
    t = s[x] + t;
    Console.Write("On the " 
      + (x + 1).ToString() 
      + (x == 0 ? "st" : (x == 1 ? "nd" : (x == 2 ? "rd" : "th"))) 
      + " day of christmas, my true love gave to me: " + t + "\n");
}

574 chars, not counting indenting. Adds some extra chars in getting the number extensions right. Can probably be improved on quite a bit, though.

Ian Varley
+3  A: 

C#

     string[] days = new string[] {"First", 
    "Second", "Third", "Fourth", "Fifth", "Sixth", 
    "Seventh", "Eighth", "Ninth", "Tenth", "Eleventh", "Twelfth"};

    string[] presents = new string[] {"a partridge in a pear tree.",
    "two turtle doves, and",
    "three french hens,", 
    "four calling birds,", 
    "five gold rings,", 
    "six geese a-laying,", 
    "seven swans a-swimming,", 
    "eigth maids a-milking,", 
    "nine ladies dancing,", 
    "ten lords a-leaping,", 
    "eleven pipers piping,", 
    "twelve drummers drumming,"};

     int cnt =0;
     foreach (string s in presents)
     {
           Console.WriteLine(string.Format("On the {0} day of Christmas my true love gave to me", days[cnt++]));
           foreach (string p in presents.Take(cnt).Reverse())
                Console.WriteLine(p);
           Console.WriteLine(System.Environment.NewLine);
     }
cgreeno
Wah! My C# version beats this by 382 characters, but I don't have any upvotes ... :( But this is nicer b/c it uses the spelled out ordinals, and I like the .Take.Reverse trick.
Ian Varley
Ian, some people have edited your version and it is now beats this by more that 382 characters.
Martin Brown
I could take out the days array as well as the spacing and that would reduce the the count by about 200....
cgreeno
why cnt++; instead of ++cnt in the Take()?
Svish
I need to put it into the days[cnt++] vs the take, but your point is still valid.
cgreeno
+3  A: 

I can't beat the Lisp version, but it's still fun.

The Delphi version:

procedure TheTwelfDaysOfChristmas(const AVerse: TStrings);
const 
  cPresentList : array[1..12] of string = (
    'a partridge in a pear tree',
    'two turtle doves, and ',
    'three french hens, ',
    'four calling birds, ',
    'five gold rings, ',
    'six geese a-laying, ',
    'seven swans a-swimming, ',
    'eigth maids a-milking, ',
    'nine ladies dancing, ',
    'ten lords a-leaping, ',
    'eleven pipers piping, ',
    'twelve drummers drumming, '
  );
  cTime : array[1..12] of string = (
    'first',
    'second',
    'third',
    'fourth',
    'fifth',
    'sixth',
    'seventh',
    'eighth',
    'nineth',
    'tenth',
    'eleventh',
    'twelfth'
  );
var
  present : string;
  i       : Integer;

begin
  present := '';
  for i := 1 to 12 do begin
    present := cPresentList[i] + present;
    AVerse.Add(Format('On the %s day of Christmas my true love gave me %s.',
      [cTime[i], present]));
  end;
end;

By the way, for all of you, Happy holidays and great programming in 2009.

Gamecat
+27  A: 

Not mine, but interesting...

This is a well-known example from http://en.wikipedia.org/wiki/Obfuscated_code (author: James O. Coplien):

#include <stdio.h>
main(t,_,a)char *a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/")
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
  :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}

"Although unintelligible at first glance, it is a legal C program that when compiled and run will generate the 12 verses of The 12 Days of Christmas. It contains all the strings required for the poem in an encoded form inlined in the code. The code iterates through the 12 days displaying what it needs to."

It won't win golf though, it is about 830 bytes.

BoltBait
Wow! That is hardcore.
Joel Marcey
I bet the guy who wrote it is a nightmare to work with....
Gordon Carpenter-Thompson
Probably. I sure wouldn't want to peer review his code!
BoltBait
Self documenting code, love it :)
Andy Webb
@BoltBait: no, the peer review would be very short and very easy to commence, in my opinion ;-)
Joachim Sauer
I use to give this code out to the programmers on my team as a 'Christmas present' - yes, that's the kind of guy I am. Actually the author is Ian Phillips (http://www.ioccc.org/years.html#1988_phillipps) who wrote it as a winning entry in an obfuscated code contest. James Coplien challenged Tom Ball to reverse engineer it in the late 90's. See http://research.microsoft.com/en-us/um/people/tball/papers/XmasGift/
DaveParillo
The recursive use of main is somehow cool. Never seen that before.
fuenfundachtzig
+4  A: 

Ruby. I think this is pretty concise (the hard work is all on one line):

days = %w{First Second Third Fourth Fifth Sixth Seventh Eighth Ninth Tenth Eleventh Twelfth}

presents = [
    "twelve drummers drumming",
    "eleven pipers piping",
    "ten lords a leaping",
    "nine ladies dancing",
    "eight maids a-milking",
    "seven swans a-swimming",
    "six geese a-laying",
    "five gold rings",
    "four calling birds",
    "three french hens",
    "two turtle doves, and",
    "a partridge in a pear tree"
    ]

0.upto(11) { |i| 
    puts "On the #{days[i]} of Christmas my true love gave to me " + presents.last(i+1).join(", ")
}
DanSingerman
It looks as though this one will generate a comma after the "and"--where none should exist.
RobH
Yes it does. I like to think of that as my own personal interpretation of the line, and where I'd put in a caesura for emphasis.
DanSingerman
+35  A: 

Using F#:

#light
open System.Net; open System.Text.RegularExpressions
printf "%s" ((new WebClient()).DownloadString("http://www.textfiles.com/holiday/12-bugs")
    |> (fun x -> (new Regex("Lines: \d+\s+([\s\S]+)--")).Match(x).Groups.[1].Value))

Twelth day outputs:

For the twelfth bug of Christmas, my manager said to me
     Tell them it's a feature
     Say it's not supported
     Change the documentation
     Blame it on the hardware
     Find a way around it
     Say they need an upgrade
     Reinstall the software
     Ask for a dump
     Run with the debugger
     Try to reproduce it
     Ask them how they did it and
     See if they can do it again.
Juliet
I think that downloading the text might be stretching the rules :)
Dan Vinton
But it is clever.
jmucchiello
I love the twelth bug of Christmas so much I've stuck it to the coffee machine.
Martin Brown
Try singing it to yourself, but make sure you're alone when you get to number five.
EnderMB
This is hysterical! Did you make it up or find it somewhere?
Dinah
+4  A: 

Using Template Toolkit

perl -MTemplate -e 'Template->new()->process("12dayxmas.tt")'

12dayxmas.tt

[%
  list = [
    { day => 'first',    item => 'A partridge in a pear tree.'},
    { day => 'second',   item => 'Two turtle doves, and '},
    { day => 'third',    item => 'Three french hens, '},
    { day => 'fourth',   item => 'Four calling birds, '},
    { day => 'fifth',    item => 'Five gold rings, '},
    { day => 'sixth',    item => 'Six geese a-laying, '},
    { day => 'seventh',  item => 'Seven swans a-swimming, '},
    { day => 'eighth',   item => 'Eight maids a-milking, '},
    { day => 'nineth',   item => 'Nine ladies dancing, '},
    { day => 'tenth',    item => 'Ten lords a-leaping, '},
    { day => 'eleventh', item => 'Eleven pipers piping, '},
    { day => 'twelfth',  item => 'Twelve drummers drumming, '}
  ];
-%]
[%
  FOREACH list;
  present = item _ present;
-%]
On the [% day %] day of Christmas my true love gave me [% present %]

[% END %]
Brad Gilbert
+6  A: 

Perl.

use Lingua::EN::Numbers qw(num2en_ordinal);
print 'On the ', num2en_ordinal($_+1),' day of Christmas my true love gave to me, ', reverse(( split /\|/, "a partridge in a pear tree.\n|two turtle doves, and |three french hens, |four calling birds, |five gold rings, |six geese a-laying, |seven swans a-swimming, |eight maids a-milking, |nine ladies dancing, |ten lords a leaping, |eleven pipers piping, |twelve drummers drumming, ")[ 0 .. $_ ]) for 0 .. 11;

( 459 Chars )

I wanted to make it a bit nicer and expressive, but this is a golf challenge.

This style violates proper coding standards somewhat. But that's golf for you.

Lingua::EN::Number

Here's the less compact version with less sneaky tricks.

use Lingua::EN::Numbers qw(num2en_ordinal);
my @gifts = (
    'a partridge in a pear tree.',
    'two turtle doves, and ',
    'three french hens, ',
    'four calling birds, ',
    'five gold rings, ',
    'six geese a-laying, ',
    'seven swans a-swimming, ',
    'eight maids a-milking, ',
    'nine ladies dancing, ',
    'ten lords a leaping, ',
    'eleven pipers piping, ',
    'twelve drummers drumming, '
);
for my $verse_id ( 0 .. $#gifts ) {
    printf 'On the %s day of Christmas my true love gave to me, ', num2en_ordinal($verse_id +1);
    print reverse @verse[ 0 .. $verse_id ];
    print "\n";
}
Kent Fredric
Couldn't you make it from 1 .. 12 instead of 0 .. 11, and then not have to do $_ + 1? You'd also have to change 0 .. $_ to 1 .. $_, but you would shave off 2 characters, and this is golf.
Chris Lutz
+4  A: 

Here's a PHP solution:

$day = Array('first','second','third','fourth','fifth','sixth','seventh',
             'eighth','ninth','tenth','eleventh','twelfth');
$gifts = Array('Twelve drummers drumming,',
               'Eleven pipers piping,',
               'Ten lords a-leaping,',
               'Nine ladies dancing,',
               'Eight maids a-milking,',
               'Seven swans a-swimming,',
               'Six geese a-laying,',
               'FIVE GOLDEN RINGS,',
               'Four calling birds,',
               'Three French hens,',
               'Two turtle doves, and',
               'A partridge in a pear tree');

for ($i = 0; $i < 12; ++$i) {
    printf("On the $day[$i] of Christmas my true love gave to me\n" . 
         implode("\n", array_slice($gifts,-($i+1))) . "\n\n");
}
jmucchiello
+3  A: 

Ruby

a=["and a partridge in a pear tree","turtle doves","French hens","calling birds","golden rings","geese a-laying","swans a-swimming","maids a-milking","ladies dancing","lords a-leaping","pipers piping","drummers drumming"]     
b=["","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve"]
c=["first","second","third","fourth","fifth","sixth","seventh","eighth","nineth","tenth","eleventh","twelfth"]
0.upto(11){|d|puts "On the "+c[d]+" day of Christmas, my true love gave to me:\n"+b[d]+" "+a[d]+",";(d-1).downto(0){|e| f=", ";f = "." if e==0;puts b[e]+" "+a[e]+f;}}

Total: 593bytes using UNIX LF.

Lucas Jones
+4  A: 
h

In my made-up language where the command h prints "Hello, World!". Oh wait, you mean that's not what we're talking about?

dancavallaro
+15  A: 
class TrueLove: ITrueLove 
{
  List<IPresent> give(int day) 
  {
    List<IPresent> lovesLabourLost = new List<IPresent>();

    //if this was C++ could you replace this with a Figgy Duff Device?
    for (int i=1; i<=day; i++)
    {
      if(day > 1 && i<=2) {lovesLabourLost .Add(new TurtleDove());}
      if(day > 2 && i<=3) {lovesLabourLost .Add(new FrenchHen());}
      if(day > 3 && i<=4) {lovesLabourLost .Add(new CallingBird());}
      if(day > 4 && i<=5) {lovesLabourLost .Add(new GOLDRING());}
      if(day > 5 && i<=6) {lovesLabourLost .Add(new LayingGeese());}
      if(day > 6 && i<=7) {lovesLabourLost .Add(new SwimmingSwan());}
      if(day > 7 && i<=8) {lovesLabourLost .Add(new MilikingMaid());}
      if(day > 8 && i<=9) {lovesLabourLost .Add(new DancingLady());}
      if(day > 9 && i<=10) {lovesLabourLost .Add(new LeapingLord());}
      if(day > 10 && i<=11) {lovesLabourLost .Add(new PipingPiper());}
      if(day > 11 && i<=12) {lovesLabourLost .Add(new DrummingDrummer());}
    }

    return lovesLabourLost && (new PartridgeInPearTree());
  }
}

static class Me: IDemanding
{
  static ITrueLove myTrueLove = new TrueLove();

  static List<IPresent> myPresents = new List<IPresent>();

  static void demandPresents()
  {
    for (int i=1; i<=daysOfChristmas; i++)
    {
      List<IPresent> MOAR = myTrueLove.give(i);

      foreach (IPresent another in MOAR)
      {
        myPresents.Add(another);
      }
    }
  }
}

const int daysOfChristmas = 12;

Me.demandPresents();
annakata
You should say what language this is, I can only assume it is Java.
Brad Gilbert
Nope, looks like C#
sk
Either it's a joke about C# or someone doesn't know how to play code golf :)
Karl
Yeah it's kind of a meta-joke, obviously a *terrible* one - move along nothing to see here...
annakata
i have up voted as I got the joke straight away looking an assuming the female gender and (lost labours love) likes the Me.demandPresents()
I was thinking of using and IDisposable TrueLove, but it would cost the myTrueLove then. No takers for the figgy duff device either :P
annakata
Don't worry, I got the figgy duff device. It's awesome. Although normally I don't like my desserts to be _too_ optimal, y'know?
Daniel Earwicker
+7  A: 

VB.Net - 530 Chars (no spaces), 634 (spaces)

Module ChristmasSong
    Sub Main()
        Dim i&, f$ : Dim d$() = {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth"}, g$() = {"a partridge in a pear tree.", "two turtle doves, and ", "three french hens, ", "four calling birds, ", "five gold rings, ", "six geese a-laying, ", "seven swans a-swimming, ", "eigth maids a-milking, ", "nine ladies dancing, ", "ten lords a-leaping, ", "eleven pipers piping, ", "twelve drummers drumming, "}
        For i = 0 To 11 : f = g(i) & f : Console.WriteLine("On the {0} day of Christmas, my true love gave to me {1}", d(i), f) : Next
    End Sub
End Module
jrcs3
You could cut this down a bit. =)* Don't waste characters on meaningful variable names in code golf when X,Y, and Z will do fine.* Don't initialize your string, rely on the compiler default. At least use "" instead of string.emptyOf course all of these are horrible advice normally.
JohnFx
You could also combine the two arrays into a single array and just add an offset to get the gifts and save yourself at least these characters "Dim gifts() {}
JohnFx
I could also get rid of j, I don't use it anywhere. I noticed that a log time a go and just let is slide.
jrcs3
+1  A: 

423 bytes with Lingua::EN::Number:

use Lingua::EN::Numbers qw/num2en num2en_ordinal/;
@l=map{($i++?num2en($i):'a')." $_"}split/\n/,<<"";
partridge in a pear tree
turtle doves, and
french hens
calling birds
gold rings
geese a-laying
swans a-swimming
maids a-milking
ladies dancing
lords a-leaping
pipers piping
drummers drumming

print"On the ".num2en_ordinal($_+1)
." day of Christmas, my true love gave to me ",
join(', ',reverse@l[0..$_]),"\n\n"for(0..11);

Or 480 bytes in perl without using Lingua::EN::Numbers:

@n=qw/first second third forth fifth sixth seventh eigth nineth tenth eleventh twelfth/;
@l=<DATA>;chomp@l;
print"On the $n[$_] day of Christmas, my true love gave to me ",
join(', ',reverse@l[0..$_]),"\n\n"for(0..11);
__DATA__
a partridge in a pear tree
two turtle doves, and 
three french hens
four calling birds 
five gold rings 
six geese a-laying
seven swans a-swimming
eight maids a-milking
nine ladies dancing
ten lords a-leaping
eleven pipers piping
twelve drummers drumming

It should be able to be reduced further since the numbers are very repetitive.

Hudson
Yeah, the only reason I didn't go for the bare-data method was I didn't want newline discrepancy issues on windows-vs-linux. with windows \r\n, your file is 17 bytes larger. :p
Kent Fredric
Does Perl on Windows put \r\n in here documents? That would be rather frustrating if things like split/\n/,<<"" adds extra \r characters.
Hudson
And using a module isn't cheating, its called "using the language" ;)"CPAN is my programming language of choice; the rest is just syntax."
Kent Fredric
if the source file is stored in a \r aware editor, perl will just parse them as if they were a literal \r in any other file. So you need to set $/ to '\r\n' for chomp to work as expected.
Kent Fredric
+3  A: 

PHP

$g = array("a partridge in a pear tree.\n",
    "two turtle doves, and",
"three french hens,",
"four calling birds,",
"five gold rings,",
"six geese a-laying,",
"seven swans a-swimming,",
"eight maids a-milking,",
"nine ladies dancing,",
"ten lords a-leaping,",
"eleven pipers piping,",
"twelve drummers drumming,"
);
$d = array("first", "second", "third", "fourth", "fifth", "sixth",
 "seventh", "eighth", "nineth", "tenth", "eleventh", "twelfth");
foreach($d as $i=>$v){
    echo "On the $v day of Christmas my true love gave to me";
    for($j=$i;$j>=0;$j--) echo " ",$g[$j];
}
Chris Bartow
+11  A: 

C#, 421 Characters

var t="";for(int i=0;i++<12;)Console.Write("On the {0}{1} day of Christmas, my true love gave to me: {2}\n",i,i<2?"st":i<3?"nd":i<4?"rd":"th",t="|a partridge in a pear tree.|two turtle doves, and |three french hens,|four calling birds,|five gold rings|six geese a-lay@seven swans a-swimm@eight maids a-milk@nine ladies danc@ten lords a-leap@eleven pipers pip@twelve drummers drumm@".Replace("@","ing,|").Split('|')[i]+t);

Spaced out version:

var t="";

for(int i = 0; i++ < 12;)
    Console.Write("On the {0}{1} day of Christmas, my true love gave to me: {2}\n",
            i,
            i < 2 ? "st" : i < 3 ? "nd" : i < 4 ? "rd" : "th",
            t="|a partridge in a pear tree.
               |two turtle doves, and 
               |three french hens,
               |four calling birds,
               |five gold rings
               |six geese a-lay
               @seven swans a-swimm
               @eight maids a-milk
               @nine ladies danc
               @ten lords a-leap
               @eleven pipers pip
               @twelve drummers drumm@"
            .Replace("@","ing,|")
            .Split('|')[i]+t);
Mindaugas Mozūras
Correct me if I'm wrong, but this looks as though it would print out "five golden ring". Where's the 's'???
RobH
You're absolutely correct. A small mistake by Martin Brown, who came up with a clever idea to use .Replace("@","ing,|"). Fixed.
Mindaugas Mozūras
+4  A: 

Python (71+467 including whitespaces)

import sys
sys.path += ["TDOC.zip"]
import TDOC
TDOC.print_verse()

Where TDOC.zip (467 bytes) contains TDOC.py:

def print_verse(presents="""\
twelve drummers drumming,
eleven pipers piping,
ten lords a-leaping,
nine ladies dancing,
eigth maids a-milking,
seven swans a-swimming,
six geese a-laying,
five gold rings,
four calling birds,
three french hens,
two turtle doves, and
a partridge in a pear tree.""".split("\n")):
    if presents: 
        print_verse(presents[1:])

        number = presents[0].split(" ", 1)[0]
        print("On the %s day of Christmas my true love gave to me %s" % (
            dict(a="first", two="second", three="third", five="fifth").get(number, number+"th"),
            " ".join(presents)))
J.F. Sebastian
+5  A: 
for d in range(12):print"On the %s day of Christmas, my true love gave to me\n\t%s\n"%("first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth".split("|")[d],"\n\t".join("twelve drummers drumming|eleven pipers piping|ten lords a-leaping|nine ladies dancing|eight maids a-milking|seven swans a-swimming|six geese a-laying|five gold rings|four calling birds|three french hens|two turtle doves and|a partridge in a pear tree.".split("|")[11-d:]))

Python, 422 chars

bd808
It contains 472 chars.
J.F. Sebastian
A: 

here are some different ways for C#

List<string> lines = new List<string>(new string[]{
    "twelve drummers drumming,\n\r"
    , "eleven pipers piping,\n\r"
    , "ten lords a-leaping,\n\r"
    , "nine ladies dancing,\n\r"
    , "eigth maids a-milking,\n\r"
    , "seven swans a-swimming,\n\r"
    , "six geese a-laying,\n\r"
    , "five gold rings,\n\r"
    , "four calling birds,\n\r"
    , "three french hens,\n\r"
    , "two turtle doves, and \n\r"
    , "a partridge in a pear tree."
    });

string[] day = {
    "first"
    ,"second"
    ,"thrid"
    ,"forth"
    ,"fifth"
    ,"six"
    ,"seventh"
    ,"eigth"
    ,"ninth"
    ,"tenth"
    ,"eleventh"
    ,"twelth"
    };


for (int i = 0; i < 12; i++)
    Console.WriteLine(string.Format("On the {0} day of christmas, my true love gave to me\n\r{1}", day[i], string.Concat(lines.GetRange(11 - i, i + 1).ToArray())));

not nessarly nice. but its small. :)

dbones
+2  A: 

Here's a Haskell version:

import Data.List
main=putStrLn$unlines$map(uncurry(\n->(++)("On the "++show n++case n of{1->"st";2->"nd";3->"rd";_->"th"}++" day of Christmas, my true love gave to me: ")))$zip[1..]$(\a->(drop 4$head a):tail a)$ map(intercalate", ".reverse)$tail$inits["and a partridge in a pair tree","two turtle doves","three french hens","four calling birds","five gold rings","six geese a-laying","seven swans a-swimming","eight maids a milking","nine ladies dancing","ten lords a-leaping","eleven pipers piping","twelve drummers drumming"]

It comes in at 527 characters. Since without good spacing it's rather incomprehensible, here's a more spread-out version:

import Data.List
main = putStrLn
       $ unlines
       $ map (uncurry (\n -> (++) ("On the " ++ show n ++ case n of { 1 -> "st"; 2 -> "nd"; 3 -> "rd"; _ -> "th"} ++ " day of Christmas, my true love gave to me: ")))
       $ zip [1..]
       $ (\a -> (drop 4 $ head a) : tail a)
       $ tail
       $ map (intercalate ", " . reverse)
             (inits ["and a partridge in a pair tree", "two turtle doves", "three french hens", "four calling birds", "five gold rings", "six geese a-laying", "seven swans a-swimming", "eight maids a milking", "nine ladies dancing", "ten lords a-leaping", "eleven pipers piping", "twelve drummers drumming"])
Gracenotes
+13  A: 

Bash:

wget -qO- http://tinyurl.com/a3xw8b

I used the output of frizzer.myopenid.com's CLisp implementation as a start.

strager
Know your tools: wget -qO - http://tinyurl.com/a3xw8b
EricSchaefer
@EricSchaefer, Odd, that doesn't work with my version of wget. I'll edit it anyway...
strager
Using `curl` is shorter.
Ben Alpert
+1  A: 
Console.WriteLine(File.ReadAllText("12daysxmas.txt"));

(It's good practise to keep string constants separate from code so you can translate them easily.)

Also here's my tribute on the forthcoming dynamic keyword in C# 4:

string lyric = "On day {0} of Christmas a dynamic gave to me {1} dynamics.";

int total = 0;
for (int day = 1; day <= 12; day++)
{
    total += day;
    Console.WriteLine(string.Format(lyric, day, total));
}

Console.WriteLine("I wonder what all these dynamics are? I guess I'll find out at runtime.");
Daniel Earwicker
Similar to my approach (in Bash). Sadly, this doesn't work on my machine. Could you include an automated installer, please?
strager
+2  A: 

Another C#

var l="a partridge in a pear tree.|two turtle doves, and|three french hens,|four calling birds,|five gold rings,|six geese a-laying,|seven swans a-swimming,|eight maids a-milking,|nine ladies dancing,|ten lords a-leaping,|eleven pipers piping,|twelve drummers drumming,".Split('|');

for (int i = 1; i < 13; i++)
    Console.Write(
        "On the {0}{2} day of christmas\rmy true love gave to me \r{1}\r\r", 
            i, 
            string.Join("\r", l.Take(i).Reverse().ToArray()), 
            (i==1?"st":i==2?"nd":i==3?"rd":"th"));

Borrowed heavily from previous answers (hey, code reuse) while adding extra savings.

481 characters once you take out unnecessary whitespace:

var l="a partridge in a pear tree.|two turtle doves, and|three french hens,|four calling birds,|five gold rings,|six geese a-laying,|seven swans a-swimming,|eight maids a-milking,|nine ladies dancing,|ten lords a-leaping,|eleven pipers piping,|twelve drummers drumming,".Split('|');for(int i=1;i<13;i++)Console.Write("On the {0}{2} day of christmas, my true love gave to me \r{1}\r\r",i,String.Join("\r",l.Take(i).Reverse().ToArray()),(i==1?"st":i==2?"nd":i==3?"rd":"th"));
Cameron MacFarland
<=12 can be written as <13.
strager
`lines` can be written as a one-letter variable, of course. =]
strager
+2  A: 

Objective-C / Cocoa

NSArray *days = [NSArray arrayWithObjects:@"first", @"second", @"third", @"forth", 
                    @"fifth", @"six", @"seventh", @"eigth", 
                    @"ninth", @"tenth", @"eleventh", @"twelth", nil];

NSArray *gifts = [NSArray arrayWithObjects:
                    @"a partridge in a pear tree.\n\n",
                    @"two turtle doves, and\n",
                    @"three french hens,\n",
                    @"four calling birds,\n",                      
                    @"five gold rings,\n",
                    @"six geese a-laying,\n",
                    @"seven swans a-swimming,\n",
                    @"eigth maids a-milking,\n",                     
                    @"nine ladies dancing,\n",
                    @"ten lords a-leaping,\n",
                    @"eleven pipers piping,\n",    
                    @"twelve drummers drumming,\n",
                    nil];

NSMutableString *aggregator = [NSMutableString string];
for(int i = 0; i < 12; i++) {
    [aggregator insertString:[gifts objectAtIndex:i] atIndex:0];
    printf("on the %s day of xmas, my true love gave to me %s", [[days objectAtIndex:i] UTF8String], [aggregator UTF8String]);
}
Ryan Townshend
+2  A: 

26 bytes!..

As the URL implies, it may be considered.. cheating:

http://github.com/dbr/so_scripts/tree/master/golf_tdoc/cheating.bash

dbr
+7  A: 

Linq to objects, in 580 characters (without whitespace)

Console.WriteLine(Enumerable.Range(1, 13).SelectMany(day =>
    Enumerable.Repeat("\nOn the " + day + 
                      (day == 1 ? "st" : 
                      (day == 2 ? "nd" : 
                      (day == 3 ? "rd" : 
                      "th"))) + " day of Christmas my true love gave to me ", 1)
              .Concat((new []
                {
                    "twelve drummers drumming,",
                    "eleven pipers piping,",
                    "ten lords a-leaping,",
                    "nine ladies dancing,",
                    "eight maids a-milking,",
                    "seven swans a-swimming,",
                    "six geese a-laying,",
                    "five gold rings,",
                    "four calling birds,",
                    "three french hens,",
                    "two turtle doves, and",
                    "a partridge in a pear tree."
                }).Reverse().Take(day).Reverse()))
              .Aggregate((a, b) => a + "\n" + b));
Daniel Earwicker
Kinda sad that my joke answer is higher rated than this, which I really worked on!
Daniel Earwicker
Okay, situation reversed. Now I'm annoyed that no one likes my joke version. This is the worst Christmas ever!
Daniel Earwicker
+8  A: 

PHP: 375 characters

$v=split(":",":a partridge in a pear tree.\n:two turtle doves, and:three french hens:four calling birds:five gold rings:six geese a-lay:seven swans a-swimm:eigth maids a-milk:nine ladies danc:ten lords a-leap:eleven pipers pip:twelve drummers drumm");while($i<12){?>On the <?=date(jS,$i*86400)," day of Christmas my true love gave to me",$s=", ".$v[++$i].($i>5?'ing':'').$s;}

Edit: updated runnable version (377) characters

<?$v=split(":",":a partridge in a pear tree.\n:two turtle doves, and:three french hens:four calling birds:five gold rings:six geese a-lay:seven swans a-swimm:eigth maids a-milk:nine ladies danc:ten lords a-leap:eleven pipers pip:twelve drummers drumm");while($i<12){?>On the <?=date(jS,$i*86400)," day of Christmas my true love gave to me",$s=", ".$v[++$i].($i>5?'ing':'').$s;}
Jasper Bekkers
This looks to be winning so far. One question: how do I run it?
fizzer
See the edit, I've made an even smaller version that is below 380 characters (377 for the runnable version). Simply save as a .php file and run in a webserver. When submitting the 380 (previous) version, I omitted <? because all other PHP submissions seem to do that as well.
Jasper Bekkers
+15  A: 

In the D programming language, using switch statement fall-through:

import std.stdio;

void main() {
    for(uint i = 1; i < 13; i++) {
        writeln("On the ", i, " day of Christmas, my true love gave to me:");
        switch(i) {
            case 12:
                writeln("twelve drummers drumming,");
            case 11:
                writeln("eleven pipers piping,");
            case 10:
                writeln("ten lords a-leaping,");
            case 9:
                writeln("nine ladies dancing,");
            case 8:
                writeln("eight maids a-milking,");
            case 7:
                writeln("seven swans a-swimming,");
            case 6:
                writeln("six geese a-laying,");
            case 5:
                writeln("five gold rings,");
            case 4:
                writeln("four calling birds,");
            case 3:
                writeln("three french hens,");
            case 2:
                writeln("two turtle doves, and");
            case 1:
                writeln("a partridge in a pear tree.\n");
        }
    }
}
dsimcha
Duff's device! (15char limit).
LiraNuna
Very nice idea!
Liran Orevi
+1  A: 

How about one line! This is in C#.

Xmas(){Console.WriteLine("On the first day of Christmas,\r\nmy true love sent to me\r\nA partridge in a pear tree.\r\n\r\nOn the second day of Christmas,\r\nmy true love sent to me\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the third day of Christmas,\r\nmy true love sent to me\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the fourth day of Christmas,\r\nmy true love sent to me\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the fifth day of Christmas,\r\nmy true love sent to me\r\nFive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the sixth day of Christmas,\r\nmy true love sent to me\r\nSix geese a-laying,\r\nFive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the seventh day of Christmas,\r\nmy true love sent to me\r\nSeven swans a-swimming,\r\nSix geese a-laying,\r\nFive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the eighth day of Christmas,\r\nmy true, love sent to me\r\nEight maids a-milking,\r\nSeven swans a-swimming,\r\nSix geese a-laying,\r\nFive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the ninth day of Christmas,\r\nmy true love sent to me\r\nNine ladies dancing,\r\nEight maids a-milking,\r\nSeven swans a-swimming,\r\nSix geese a-laying,\r\nFive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the tenth day of Christmas,\r\nmy true love sent to me\r\nTen lords a-leaping,\r\nNine ladies dancing,\r\nEight maids a-milking,\r\nSeven swans a-swimming,\r\nSix geese a-laying,\r\nfive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the eleventh day of Christmas,\r\nmy true love sent to me\r\nEleven pipers piping,\r\nTen lords a-leaping,\r\nNine ladies dancing,\r\nEight maids a-milking,\r\nSeven swans a-swimming,\r\nSix geese a-laying\r\nFive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree.\r\n\r\nOn the twelfth day of Christmas,\r\nmy true love sent to me\r\nTwelve drummers drumming,\r\nEleven pipers piping,\r\nTen lords a-leaping,\r\nNine ladies dancing,\r\nEight maids a-milking,\r\nSeven swans a-swimming,\r\nSix geese a-laying,\r\nFive golden rings,\r\nFour calling birds,\r\nThree French hens,\r\nTwo turtle doves,\r\nAnd a partridge in a pear tree!");}
The Alpha Nerd
OMG> :/ Thats So Awesome (!)
Kent Fredric
Congratulations on reading the title of the question.
David Thornley
A: 

Didn't see any for Java (which isn't known for its minimal syntax btw) so first I made this

String g;
public void sing() {
 g = "";  
 for(Entry<?,?> e : mm("first", "a partridge in a pear tree",
        "second", "two turtle doves, and ",
        "third", "three french hens, ",
        "fourth", "four calling birds, ",
        "fifth", "five gold rings, ",
        "sixth", "six geese a-laying ",
        "seventh", "seven swans a-swimming, ",
        "eigth", "eight maids a-milking, ",
        "ninth", "nine ladies dancing, ",
        "tenth", "ten lords a-leaping, ",
        "eleventh", "eleven pipers piping, ",
        "twelfth", "twelve drummers drumming, ").entrySet()) {
  System.out.println("On the "+e.getKey()+
    " day of Christmas my true love gave to me "+e.getValue()+".");
 }
}

public Map<?,?> mm(String... s) {
 Map m = new LinkedHashMap();
 for(int i=0;i<s.length;i=i+2) {
  g = s[i+1] + g;
  m.put(s[i], g);
 }
 return m;
}

and realized it's rather complex (weighs 708 chars) so then I went for a more simpler solution (adapted from other answers, line changes only for readability):

public void sing() {
    String s = "";
    String[]d={"first","second","third","fourth",
        "fifth","sixth","seventh","eighth",
        "ninth","tenth","eleventh","twelfth"};
    String[]g={"a partridge in a pear tree",
        "two turtle doves, and ",
        "three french hens, ",
        "four calling birds, ",
        "five gold rings, ",
        "six geese a-laying ",
        "seven swans a-swimming, ",
        "eight maids a-milking, ",
        "nine ladies dancing, ",
        "ten lords a-leaping, ",
        "eleven pipers piping, ",
        "twelve drummers drumming, "};
    int i=0;
    while(i<12)
     System.out.println("On the "+d[i]+" day of Christmas my true love gave to me "+
   (s=g[i++]+s)+".");
}

which is 576 chars without whitespaces, if the method signature is switched to proper main() then it's 596.

If I had interest to make a third version, I'd try the enum trick too.

Esko
A: 

Ruby: 458 chars
(+ 4 newlines added to keep it under 80 columns)

n=%w{first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth}
s=''
["a partridge in a pear tree","two turtle doves, and","three french hens",
"four calling birds","five gold rings","six geese a-laying","seven swans a-swimming",
"eight maids a-milking","nine ladies dancing","ten lords a leaping",
"eleven pipers piping","twelve drummers drumming"].map{|p|
puts "On the #{n.pop} day of Christmas my true love gave to me: "+(s=p+', '+s)}
AShelly
+11  A: 

In C++ you'd

std::cout << boost::12_days_of_christmas;
Jasper Bekkers
you forgot to #include <boost/golfing_for_cats.h>
metao
I hate to nitpick such a lovely solution, but I'm fairly sure C++ identifiers cannot begin with a digit.
TokenMacGuy
@TokenMacGuy I've been expecting that answer since I hit the post button :-)
Jasper Bekkers
+2  A: 

C#: 395 chars (not including whitespace...)

for (var x = 0; x++ < 12; )
    Console.Write(
        "On the {0} day of Christmas,\nMy true love gave to me\n{1}\n\n",
        x + (x < 2 ? "st" : x < 3 ? "nd" : x < 4 ? "rd" : "th"),
        String.Join(
            "\n",
            "a partridge in a pear tree.|turtle doves and|french hens|calling birds|gold rings|geese a-laying|swans a-swimming|maids a-milking|ladies dancing|lords a-leaping|pipers piping|drummers drumming"
                .Split('|').Take(x).Select((y, i) => (i > 0 ? (i + 1) + " " : "") + y).Reverse().ToArray()
        )
    );
BenAlabaster
+2  A: 

Here's an erlang version (~586 chars):

-module (xmas).
-export ([xmas/0]).
xmas() ->
 W = ["twelve drummers drumming, ",
 "eleven pipers piping, ",
 "ten lords a-leaping, ",
 "nine ladies dancing, ",
 "eight maids a-milking, ",
 "seven swans a-swimming, ",
 "six geese a-laying, ",
 "five gold rings, ",
 "four calling birds, ",
 "three french hens, ",
 "two turtle doves, and ",
 "a partridge in a pear tree."],
 io:format(lists:foldl(
 fun(X,Acc) -> Acc ++ X ++ "~n" end, "",
 ["On the " ++ day_str(Q) ++ 
 " day of Christmas, my true love gave me " ++ 
 lists:foldl(
  fun(X,Acc)-> Acc++X end,
  "", lists:nthtail(12-Q,W)) || 
  Q <- lists:seq(1,12)]),[]).
day_str(Q) ->
 case Q of
  1 -> "1st";
  2 -> "2nd";
  3 -> "3rd";
  N -> erlang:integer_to_list(N,10) ++ "th"
 end.
cheng81
+1  A: 

Java, based on Esko's second solution:

class C{
    public static void main(String[]d){
        String s="";
        d="first1second1third1fourth1fifth1sixth1seventh1eighth1ninth1tenth1eleventh1twelfth".split("1");
        String[]g="a partridge in a pear tree1two turtle doves,\nand 1three french hens,\n1four calling birds,\n1five gold rings,\n1six geese a-laying\n1seven swans a-swimming,\n1eight maids a-milking,\n1nine ladies dancing,\n1ten lords a-leaping,\n1eleven pipers piping,\n1twelve drummers drumming,\n".split("1");
        for(int i=0;i<12;)
            System.out.println("On the "+d[i]+" day of Christmas my true love gave to me:\n"+
                    (s=g[i++]+s)+".\n");
    }
}

If I counted correctly, that's 579 characters (not counting indentation and newlines). And this one is completely runnable, and doesn't print each verse on one line. The output is:

On the first day of Christmas my true love gave to me:
a partridge in a pear tree.

On the second day of Christmas my true love gave to me:
two turtle doves, and
a partridge in a pear tree.

On the third day of Christmas my true love gave to me:
three french hens,
two turtle doves, and
a partridge in a pear tree.

...


EDIT: Slightly improved version, based on balabaster's idea of replacing a common string with one character:

class C{
    public static void main(String[]d){
        String s="";
        d="first1second1third1fourth1fifth1sixth1seventh1eighth1ninth1tenth1eleventh1twelfth".split("1");
        String[]g="a partridge in a pear tree1two turtle doves,\nand 1three french hens,\n1four calling birds,\n1five gold rings,\n1six geese a-lay#seven swans a-swimm#eight maids a-milk#nine ladies danc#ten lords a-leap#eleven pipers pip#twelve drummers drumm#".replace("#","ing,\n1").split("1");
        for(int i=0;i<12;)
            System.out.println("On the "+d[i]+" day of Christmas my true love gave to me:\n"+
                (s=g[i++]+s)+".\n");
    }
}

It's now down to 562 chars (even though I added a comma that I'd missed before).

Michael Myers
A: 

A C/C++ version using a single buffer and pointer arithmetic. A single include, one declaration and technically only two lines of code in main to do the printing:

#include <stdio.h>

char *days =
    "twelve drummers drumming,  \n"
    "eleven pipers piping,      \n"
    "ten lords a-leaping,       \n"
    "nine ladies dancing,       \n"
    "eight maids a-milking,     \n"
    "seven swans a-swimming,    \n"
    "six geese a-laying,        \n"
    "five gold rings,           \n"
    "four calling birds,        \n"
    "three french hens,         \n"
    "two turtle doves, and      \n"
    "a partridge in a pear tree.\n\n";

void main()
{
    for (int i = 1; i <= 12; i++)
     printf("On the %d%s day of Christmas, my true love gave to me:\n%s",
       i,i == 1 ? "st" : (i == 2 ? "nd" : "th"), days + (12-i)*28);
}
A: 

Pretty straightforward solution in C++:

#include <iostream.h>
char*a[]={"a partridge in a pear tree.\n","two turtle doves, and","three french hens,","four calling birds,","five gold rings,","six geese a-laying,","seven swans a-swimming,","eight maids a-milking,","nine ladies dancing,","ten lords a-leaping,","eleven pipers piping,","twelve drummers drumming,"};
char*b[]={"first","second","third","fourth","fifth","sixth","seventh","eighth","nineth","tenth","eleventh", "twelfth"};
int main(){for(int i=0;i<12;i++){std::cout<<"On the "<<b[i]<<" day of Christmas my true love gave to me, \n";for(int j=i;j>=0;j--)std::cout<<a[j]<<" \n";}}

595 characters, though it could be reduced to 513 characters if you allow the "1st, 2nd, 3rd" etc notation that some have used.

Aistina
A: 

LUA 540 (without tabs & returns)

t={"twelve drummers drumming,","eleven pipers piping,","ten lords a-leaping,","nine ladies dancing,","eight maids a-milking,","seven swans a-swimming,","six geese a-laying,","five gold rings,","four calling birds,","three french hens,","two turtle doves, and","a partridge in a pear tree."} 

f=function(i) 
    r=i.."th" 
    if (i==1) then r=i.."st" 
    elseif (i==2) then r=i.."nd" 
    elseif (i==3) then r=i.."rd" 
    end 
    return r 
end 

for i=1,12 do 
    s="On the "..f(i).." day of Christmas my true love gave to me" 
    for j=13-i,12 do 
     s=s.." "..t[j] 
    end 
    print(s) 
end

Unfortunately we don't have a string to array function or a way to do "first" via the date library. Runs correctly at http://www.lua.org/cgi-bin/demo

Nick
+1  A: 

Python, 436 chars

(443 including optional newlines)

print """
eJzlk91xxCAMhN9TxRZwSRMp4GpQjGw04ccDunOu+wjcgMkkk8vlxRjQst9q4JygnjFLqQpHN+QZ
r75I1UgV8QYtF0bIV8ZC9tGMyCCsVLSIWxiS2pSpWCnzy9N5P7HylJM7fqRuGXopGhjOtuoJZPID
RuqljPh4E2MunCYPz8mMvmw9Z1P5496tHhOFIGnBm2E38+/kkXkIR9o8B4diQGbz03xVPkb4rBwL
c7X79hzoZlCnX2DmK6ch6iZA3ShV466bxNjJ7yINy6J+JE0XIJK4liZKeN/D3HPIJIlHMrZ6BHLC
1URp6tR/MbiO3VQrt7XSAwamtUM/TDM4jL7cXYFVVi61DR38sbukG4fr0GvZFXDlEmPrU//Z8/+j
/n0CsHRGTA==
""".decode("base64").decode("zlib")
MizardX
A: 

Even though it's been over for a while, I still like to try out these code golf challenges...

Best I could do with MATLAB: 383 chars (after removing whitespace and line continuation symbols)

a = {'twelve drummers drumming';...
     'eleven pipers piping';...
     'ten lords a-leaping';...
     'nine ladies dancing';...
     'eight maids a-milking';...
     'seven swans a-swimming';...
     'six geese a-laying';...
     'five gold rings';...
     'four calling birds';...
     'three french hens';...
     'two turtle doves and';...
     'a partridge in a pear tree.';’’};
b = {'st','nd','rd','th'};
for i = 1:12,...
  disp(char(['On the ',num2str(i),b{min(i,4)},...
             ' day of Christmas my true love gave to me'],...
            a{13-i:13}));...
end
gnovice
A: 

Here's a Javascript version. The best I could do was 497 characters when compressed.

s = "", k = "ing, ", t = [":first:a:partridge in a pear tree", 
                ":second:two:turtle doves, and ", 
                "th:ird:ree:french hens, ",
                "four:th::calling birds, ", 
                "fi:fth:ve:gold rings, ", 
                "six:th::geese a-lay" + k,
                "seven:th::swans a-swimm" + k,
                "eight:h::maids a-milk" + k,
                "nin:th:e:ladies danc" + k, 
                "ten:th::lords a-leap" + k,
                "eleven:th::pipers pip" + k,
                "twel:fth:ve:drummers drumm"]

for (i = 0; i < 12; i++)
    document.write("On the " + (v = t[i].split(":"))[0] + v[1]
                    + " day of Christmas my true love gave to me "
                    + (s = v[0] + v[2] + " " + v[3] + s) + "<p>")



s="",k="ing, ",t=[":first:a:partridge in a pear tree",":second:two:turtle doves, and ","th:ird:ree:french hens, ","four:th::calling birds, ","fi:fth:ve:gold rings, ","six:th::geese a-lay"+k,"seven:th::swans a-swimm"+k,"eight:h::maids a-milk"+k,"nin:th:e:ladies danc"+k,"ten:th::lords a-leap"+k,"eleven:th::pipers pip"+k,"twel:fth:ve:drummers drumm"];for(i=0;i<12;i++)document.write("On the "+(v=t[i].split(":"))[0]+v[1]+" day of Christmas my true love gave to me "+(s=v[0]+v[2]+" "+v[3]+s)+"<p>")
Adam
+1  A: 

This isn't going to win, but here's my Java version (compilable and runnable) in 576 characters.

class T{enum D{first,second,third,fourth,fifth,sixth,seventh,eighth,ninth,tenth,eleventh,twelfth}public static void main(String[] args){String o="",s="s, ",i="ing, ";String t[]={"a partridge in a pear tree","two turtle doves, and ","three french hen"+s,"four calling bird"+s,"five gold ring"+s,"six geese a-lay"+i,"seven swans a-swimm"+i,"eight maids a-milk"+i,"nine ladies danc"+i,"ten lords a-leap"+i,"eleven pipers pip"+i,"twelve drummers drumm"+i};int j=0;while(j<12)System.out.println("On the "+D.values()[j]+" day of Christmas my true love gave to me "+(o=t[j++]+o));}}
Adam
Just tried it out - very nice!
John Topley
A: 

Isn't this included in the F# powerpack somewhere... :)

+4  A: 

LilyPond, 340 characters (shorter than Common Lisp)

'Tis the season! (And rather fitting, given that LilyPond is primarily used to typeset music... One can easily adapt this code to produce sheet music for the song in addition to just the lyrics.)

Adapted from fizzer's solution.

#(map(lambda(x)(format #t"On the ~:R day of Christmas my true love gave to me~{ ~R~:*~[~;~;turtle doves and~;French hens,~;calling birds,~;gold rings,~;geese a-laying,~;swans a-swimming,~;maids a-milking,~;ladies dancing,~;lords a-leaping,~;pipers piping,~;drummers drumming,~]~} a partridge in a pear tree.
"x(iota(1- x)x -1)))(iota 12 1))

Usage: $ lilypond thisfile.ly

This version, in 341 characters, matches fizzer's output exactly, but is three bytes shorter:

#(map(lambda(x)(format #t"On the ~:R day of Christmas my true love gave to me~{
~R ~:*~[~;~;turtle doves and~;french hens,~;calling birds,~;gold rings,~;geese a-laying,~;swans a-swimming,~;maids a-milking,~;ladies dancing,~;lords a-leaping,~;pipers piping,~;drummers drumming,~]~}
a partridge in a pear tree

"x(iota(1- x)x -1)))(iota 12 1))
KirarinSnow
A: 

Stumbled on this thread and it looked like so much fun I couldn't resist - here's another JavaScript version - it's not the shortest but I like the way it uses recursion and closure inside of a loop.

(function(){
    var v = [
        {d:'first', p:'a partridge in a pear tree'},
        {d:'second', p:'two turtle doves, and '},
        {d:'third', p:'three french hens, '},
        {d:'fourth', p:'four calling birds, '},
        {d:'fifth', p:'five gold rings, '}, 
        {d:'sixth', p:'six geese a-laying, '}, 
        {d:'seventh', p:'seven swans a-swimming, '},
        {d:'eighth', p:'eight maids a-milking, '},
        {d:'ninth', p:'nine ladies dancing, '}, 
        {d:'tenth', p:'ten lords a-leaping, '},
        {d:'eleveth', p:'eleven pipers piping, '},
        {d:'twelth', p:'twelve drummers drumming, '}
    ];
    for (var i=0;i<12;i++)
    {
        document.write('On the '+v[i].d+' day of Christmas my true love gave to me ');
        (function(i){
            document.write(v[i].p);
            if (i>0)
            {
                arguments.callee(--i);
            }
        })(i);
        document.write('.<p>');
    }
})();
John