Code Golf: Print the entire "12 Days of Christmas" song in the fewest lines of code
Asked Answered
B

45

25

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)

Brunell answered 20/12, 2008 at 15:21 Comment(5)
I do not get it... a simple echo with the smallest verses will win... not really a code golf...Geanticlinal
A link to the 12 verses for non-Americans?Immunogenic
@Daok - the verses accumulate, so there are about 90 lines - too much to echo.Devotional
Ok before your edit I thought you asked to show those 12 lines :PGeanticlinal
Some of us would prefer Hava Nagila code golf. ;)Belonging
D
44

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.

Devotional answered 20/12, 2008 at 15:21 Comment(4)
There will be a smart way to get rid of the cardinals with ~R, but it escapes me at the momentDevotional
You have a typo on day 8. "eigth" should be "eight".Forborne
Since when does lisp come with a perl interpreter?Spier
its ok to accept your own answers, you just don't get reputation for it.Cession
D
37

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.
Delative answered 20/12, 2008 at 15:21 Comment(4)
I think that downloading the text might be stretching the rules :)Koroseal
I love the twelth bug of Christmas so much I've stuck it to the coffee machine.Hestia
Try singing it to yourself, but make sure you're alone when you get to number five.Deerdre
This is hysterical! Did you make it up or find it somewhere?Dialogue
D
27

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.

Discernible answered 20/12, 2008 at 15:21 Comment(3)
@BoltBait: no, the peer review would be very short and very easy to commence, in my opinion ;-)Escutcheon
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 (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 research.microsoft.com/en-us/um/people/tball/papers/XmasGiftMcgowen
The recursive use of main is somehow cool. Never seen that before.Trstram
V
15

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");
        }
    }
}
Vitale answered 20/12, 2008 at 15:21 Comment(1)
Duff's device! (15char limit).Machos
B
15
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();
Bomarc answered 20/12, 2008 at 15:21 Comment(6)
You should say what language this is, I can only assume it is Java.Dissyllable
Either it's a joke about C# or someone doesn't know how to play code golf :)Distend
Yeah it's kind of a meta-joke, obviously a terrible one - move along nothing to see here...Bomarc
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()Weld
I was thinking of using and IDisposable TrueLove, but it would cost the myTrueLove then. No takers for the figgy duff device either :PBomarc
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?Differentiable
S
14

In C++ you'd

std::cout << boost::12_days_of_christmas;
Spier answered 20/12, 2008 at 15:21 Comment(3)
you forgot to #include <boost/golfing_for_cats.h>Tarango
I hate to nitpick such a lovely solution, but I'm fairly sure C++ identifiers cannot begin with a digit.Lavonlavona
@TokenMacGuy I've been expecting that answer since I hit the post button :-)Spier
S
14

Bash:

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

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

Sommers answered 20/12, 2008 at 15:21 Comment(1)
@EricSchaefer, Odd, that doesn't work with my version of wget. I'll edit it anyway...Sommers
T
11

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);
Triplett answered 20/12, 2008 at 15:21 Comment(2)
Correct me if I'm wrong, but this looks as though it would print out "five golden ring". Where's the 's'???Trojan
You're absolutely correct. A small mistake by Martin Brown, who came up with a clever idea to use .Replace("@","ing,|"). Fixed.Urinary
S
9

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;}
Spier answered 20/12, 2008 at 15:21 Comment(2)
This looks to be winning so far. One question: how do I run it?Devotional
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.Spier
D
7

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));
Differentiable answered 20/12, 2008 at 15:21 Comment(2)
Kinda sad that my joke answer is higher rated than this, which I really worked on!Differentiable
Okay, situation reversed. Now I'm annoyed that no one likes my joke version. This is the worst Christmas ever!Differentiable
F
7

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
Franck answered 20/12, 2008 at 15:21 Comment(3)
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.empty Of course all of these are horrible advice normally.Sox
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() {}Sox
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.Franck
C
6

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))
Cohune answered 20/12, 2008 at 15:21 Comment(0)
R
6
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

Rolo answered 20/12, 2008 at 15:21 Comment(0)
H
6

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";
}
Howdy answered 20/12, 2008 at 15:21 Comment(1)
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.Schnapps
P
5

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(", ")
}
Preservative answered 20/12, 2008 at 15:21 Comment(2)
It looks as though this one will generate a comma after the "and"--where none should exist.Trojan
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.Preservative
N
4

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)))
Naldo answered 20/12, 2008 at 15:21 Comment(0)
M
4
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?

Mart answered 20/12, 2008 at 15:21 Comment(0)
A
4

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");
}
Aporia answered 20/12, 2008 at 15:21 Comment(0)
D
4

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 %]
Dissyllable answered 20/12, 2008 at 15:21 Comment(0)
A
3

26 bytes!..

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

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

Alit answered 20/12, 2008 at 15:21 Comment(0)
R
3

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];
}
Roseola answered 20/12, 2008 at 15:21 Comment(0)
W
3

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.

Whap answered 20/12, 2008 at 15:21 Comment(0)
H
3

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.

Herbart answered 20/12, 2008 at 15:21 Comment(0)
F
3

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);
     }
Fluency answered 20/12, 2008 at 15:21 Comment(5)
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.Exploratory
Ian, some people have edited your version and it is now beats this by more that 382 characters.Hestia
I could take out the days array as well as the spacing and that would reduce the the count by about 200....Fluency
why cnt++; instead of ++cnt in the Take()?Alcus
I need to put it into the days[cnt++] vs the take, but your point is still valid.Fluency
E
3

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.

Exploratory answered 20/12, 2008 at 15:21 Comment(0)
H
2

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
Handfast answered 20/12, 2008 at 15:21 Comment(0)
F
2

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")
Fae answered 20/12, 2008 at 15:21 Comment(0)
V
2

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.
Vigue answered 20/12, 2008 at 15:21 Comment(0)
W
2

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()
        )
    );
Warder answered 20/12, 2008 at 15:21 Comment(0)
T
2

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!");}
Terbecki answered 20/12, 2008 at 15:21 Comment(0)
A
2

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]);
}
Alexalexa answered 20/12, 2008 at 15:21 Comment(0)
P
2

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")); 
Plutus answered 20/12, 2008 at 15:21 Comment(1)
lines can be written as a one-letter variable, of course. =]Sommers
B
2

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"])
Blida answered 20/12, 2008 at 15:21 Comment(0)
G
1

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));}}
Grams answered 20/12, 2008 at 15:21 Comment(0)
M
1

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

Metallophone answered 20/12, 2008 at 15:21 Comment(0)
F
1

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)}
Follett answered 20/12, 2008 at 15:21 Comment(0)
D
1
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.");
Differentiable answered 20/12, 2008 at 15:21 Comment(1)
Similar to my approach (in Bash). Sadly, this doesn't work on my machine. Could you include an automated installer, please?Sommers
I
1

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.

Irenairene answered 20/12, 2008 at 15:21 Comment(4)
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. :pHowdy
Does Perl on Windows put \r\n in here documents? That would be rather frustrating if things like split/\n/,<<"" adds extra \r characters.Irenairene
And using a module isn't cheating, its called "using the language" ;) "CPAN is my programming language of choice; the rest is just syntax."Howdy
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.Howdy
S
0

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>');
    }
})();
Schlesinger answered 20/12, 2008 at 15:21 Comment(0)
G
0

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>")
Grams answered 20/12, 2008 at 15:21 Comment(0)
G
0

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

Generalization answered 20/12, 2008 at 15:21 Comment(0)
A
0

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.

Apograph answered 20/12, 2008 at 15:21 Comment(0)
S
0

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);
}
Sundstrom answered 20/12, 2008 at 15:21 Comment(0)
O
0

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.

Outlaw answered 20/12, 2008 at 15:21 Comment(0)
P
0

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

Pellikka answered 20/12, 2008 at 15:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.