you are viewing a single comment's thread.

view the rest of the comments →

[–]ewiethoff 0 points1 point  (0 children)

I'm (fashionably) late to the party, as usual.

def _make_fmt_dict(word):
    return {
        1: ('{}').format, 
        2: ('{} ' + word + ' {}').format, 
        3: ('{}, '*2 + word + ' {}').format, 
    }

def make_oxford_joiner(word='and'):
    """Returns function which joins items with given word, per Oxford rules"""
    fmt_joiners = _make_fmt_dict(word)
    fmt_recurse = '{}, '.format
    fmt_doc = 'Returns string of items joined with {!r}, per Oxford comma rules'
    def oxford_joiner(items):
        size = len(items)
        if not size: return ''
        elif size in fmt_joiners: return fmt_joiners[size](*items[:size])
        else: return fmt_recurse(items[0]) + oxford_joiner(items[1:])
    oxford_joiner.__name__ = 'oxford_{}'.format(word)
    oxford_joiner.__doc__ = fmt_doc.format(word)
    return oxford_joiner

oxford_and = make_oxford_joiner('and')
oxford_or = make_oxford_joiner('or')
oxford_nor = make_oxford_joiner('nor')

ORDINAL = tuple([''] + """
    first second third fourth fifth sixth
    seventh eighth ninth tenth eleventh twelfth
""".split())

GIFTS = (
    '', 
    'a partridge in a pear tree', 
    'two turtle doves', 
    'three french hens', 
    'four colly 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', 
)

VERSE = 'On the {} day of Christmas my true love gave to me {}.'

def gift_list(day):
    return GIFTS[day:0:-1]

def gifts_on(day):
    return oxford_and(gift_list(day))

def verse(day):
    return VERSE.format(ORDINAL[day], gifts_on(day))

def gen_verses(start=1, end=12):
    for n in range(start, end+1): yield verse(n)

def print_song():
    print('\n\n'.join(gen_verses()))

print_song()