In [1]:
from __future__ import print_function
import cStringIO
In [2]:
import inflect
p = inflect.engine()
In [3]:
# This works fine, but I hate typing those numbers.
gifts = [
'a partridge in a pear tree',
'two turtle doves',
'three french hens',
]
In [4]:
unnumbered_gifts = [
'partridge in a pear tree',
'turtle doves',
'french hens',
'calling birds',
'gold rings',
'geese-a-laying',
'swans-a-swimming',
'maids-a-milking',
'ladies dancing',
'lords-a-leaping',
'pipers piping',
'drummers drumming',
]
In [5]:
# This works, but the if/else is too complex, too ugly.
gifts = [
' '.join([(p.number_to_words(i) if i > 1 else 'a'), gift])
for i, gift in enumerate(unnumbered_gifts, 1)]
gifts
Out[5]:
In [6]:
# This is more straightforward, handling the idiomatic 'a' separately.
gifts = [
p.number_to_words(i) + ' ' + gift
for i, gift in enumerate(unnumbered_gifts, 1)]
gifts[0] = gifts[0].replace('one', 'a', 1)
gifts
Out[6]:
In [7]:
def combine(items, separator, last_separator):
terms_before_last = separator.join(items[:-1])
if terms_before_last:
return last_separator.join([terms_before_last, items[-1]])
else:
return items[-1]
if False:
print(combine(['one', 'two', 'three'], '\n', '\nand '))
print(combine(['uno', 'dos'], '\n', '\nand '))
print(combine(['one'], '\n', '\nand '))
In [8]:
if True:
gifts = gifts[:3]
In [9]:
gifts.reverse()
In [10]:
# The 1s in the range argments are a bit awkward.
for n in range(1, len(gifts)+1):
nth = p.number_to_words(p.ordinal(n))
print('On the %s day of Christmas, my true love sent to me' % nth)
print(combine(gifts[-n:], '\n', '\nand ') + '.')
print()
In [11]:
# The n += 1 is straightforward now, but the range(len()) is awkward.
for n in range(len(gifts)):
n += 1
nth = p.number_to_words(p.ordinal(n))
print('On the %s day of Christmas, my true love sent to me' % nth)
print(combine(gifts[-n:], '\n', '\nand ') + '.')
print()
In [12]:
# That I ignore the iterated gift is awkward.
# The enumeration is nice.
for n, dont_care in enumerate(gifts, 1):
nth = p.number_to_words(p.ordinal(n))
print('On the %s day of Christmas, my true love sent to me' % nth)
print(combine(gifts[-n:], '\n', '\nand ') + '.')
print()
In [13]:
# For TDD, avoid I/O in function.
def make_lyrics():
output = cStringIO.StringIO()
for n, dont_care in enumerate(gifts, 1):
nth = p.number_to_words(p.ordinal(n))
print('On the %s day of Christmas, my true love sent to me' % nth, file=output)
print(combine(gifts[-n:], '\n', '\nand ') + '.', file=output)
print(file=output)
return output.getvalue()
In [14]:
# For TDD, avoid I/O in function.
def make_lyrics():
lyrics = []
for n, dont_care in enumerate(gifts, 1):
nth = p.number_to_words(p.ordinal(n))
lyrics.extend([
'On the %s day of Christmas, my true love sent to me' % nth,
combine(gifts[-n:], '\n', '\nand ') + '.',
'',
])
return '\n'.join(lyrics)
In [15]:
print(make_lyrics())
In [16]:
with open('12doc.lyrics', 'w') as file:
file.write(make_lyrics())
!! espeak <12doc.lyrics 2>/dev/null
Out[16]: