A Partridge In A Pear Tree
December 23, 2016
You all know the old song:
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.
On the fourth day of Christmas my true love gave to me four calling birds, three French hens, two turtle doves and a partridge in a pear tree.
On the fifth day of Christmas my true love gave to me five golden rings, four calling birds, three French hens, two turtle doves and a partridge in a pear tree.
On the sixth day of Christmas my true love gave to me six geese a-laying, five golden rings, four calling birds, three French hens, two turtle doves and a partridge in a pear tree.
On the seventh day of Christmas my true love gave to me 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.
On the eighth day of Christmas my true love gave to me 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.
On the ninth day of Christmas my true love gave to me 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.
On the tenth day of Christmas my true love gave to me 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.
On the eleventh day of Christmas my true love gave to me 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.
On the twelfth day of Christmas my true love gave to me 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.
Your task is to write a program that prints the words of the song, as economically as possible. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
I wish you a Merry Christmas and a Happy New Year.
425 character in Common Lisp:
Oops, sorry, the bzip2 -9 file is actually only 429 bytes:
Here’s a little C program (there are a couple of Obfuscated C competition programs that are worth a look). Not quite as short as Pascal’s (hard to compete with a language with built-in printing of numbers as ordinals):
Here’s some JS as well:
Merry Christmas all.
Here’s the 12 days in MUMPS:
twelvedays ;
n i,j,nth
f i=1:1:12 d
. s nth=$p($t(days),”;”,i+1)
. w !,”On the “,nth,” day of Christmas my true love gave to me”
. f j=i:-1:1 d
. . w ” ”
. . w $p($t(presents+j),”;”,2)
. . i j>2 w “,”
. . e w $s(j=2:” and”,1:”.”)
q
;
days ;first;second;third;fourth;fifth;sixth;seventh;eighth;ninth;tenth;eleventh;twelfth
presents ;
;a partridge in a pear tree
;two turtle doves
;three French hens
;four calling birds
;five golden 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
I thought I would try in Python:
gifts = {
'twelvth': 'twelve drummers drumming',
'eleventh': 'eleven pipers piping',
'tenth': 'ten lords a-leaping',
'ninth': 'nine ladies dancing',
'eighth': 'eight maids a-milking',
'seventh': 'seven swans a-swimming',
'sixth': 'six geese a-laying',
'fifth': 'five golden rings',
'fourth': 'four calling birds',
'third': 'three French hens',
'second': 'two turtle doves and ',
'first': 'a partridge in a pear tree.',
}
days = ('first', 'second', 'third', 'fourth', 'fifth', 'sixth',
'seventh', 'eighth', 'ninth', 'tenth', 'eleventh', 'twelvth')
def first_part(day):
print("On the {} day of Christmas"
" my true love gave to me ".format(day), end="")
def second_part(gift, comma=True):
print(gift, end="")
print(end=", ") if comma else None
for day in days:
first_part(day)
for i in range(days.index(day), -1, -1):
comma = False if (i == 0 or i == 1) else True
gift = gifts[days[i]]
second_part(gift, comma)
print()
Actually, I quite like the obfuscated C version, and it is easy to de-obfuscate:
(let ((p “On the ~:r day of Christmas my true love gave to me ~a~%”)
(r “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.”))
(let loop ((i ‘(236 215 196 176 157 137 113 90 69 48 26 0))
(c 1))
(if (not (null? i))
(begin
(format #t p c (substring r (car i)))
(loop (cdr i) (+ c 1))))))
But a constructive version could also make use of format, although its dsl is very unschemely:
(let ((p “On the ~:r day of Christmas my true love gave to me ~a~%”))
(let loop ((r ‘(“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”))
(s “a partridge in a pear tree.”)
(c 1))
(format #t p c s)
(if (not (null? r))
(begin
(loop (cdr r)
(format #f “~r ~a~a ~a” (+ c 1) (car r) (if (= c 1) ” and” “,”) s)
(+ c 1))))))
@Michael: Thanks, I wasn’t particularly intending to be obfuscated, just compact. For real C obfuscation see, eg: http://www.ioccc.org/1988/phillipps.c
That program does actually print out The Twelve Days of Christmas, if it’s not clear from the code.
Happy New Year to all.