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.