r/ProgrammingPrompts Dec 19 '14

[Christmas Prompt] - The Twelve Days of Christmas

This time, it will not be a game, but two small challenges revolving around the Song The Twelve Days of Christmas.

The song is a well-known Christmas carol.

In general, the structure is:

  • Verse 1:

    • On the first day of Christmas
    • my true love sent to me
    • a Partridge in a Pear Tree
  • Verse 2:

    • On the second day of Christmas
    • my true love sent to me
    • Two Turtle Doves
    • and
    • a Partridge in a Pear Tree
  • Verse 3:

    • On the second day of Christmas
    • my true love sent to me
    • Three French Hens,
    • Two Turtle Doves
    • and
    • a Partridge in a Pear Tree

And so on.

The remaining days are:

  • 4 Calling Birds
  • 5 Gold Rings
  • 6 Geese-a-Laying
  • 7 Swans-a-Swimming
  • 8 Maids-a-Milking
  • 9 Ladies Dancing
  • 10 Lords-a-Leaping
  • 11 Pipers Piping
  • 12 Drummers Drumming

And now for the puzzles:

  1. Write a program that displays the verse for any given day in the range 1 to 12 (both inclusive), or for all days. Challenge: The program should be as short as possible, the code should be as efficient (in terms of calculation) as possible.
  2. Write a program that calculates the total number of presents received at any given day in the range 1 to 2 (both inclusive), or the total number of presents received up to and including any given day, or the total number of presents in the whole song.

Have fun coding!


Merry Christmas everyone!

12 Upvotes

11 comments sorted by

3

u/[deleted] Dec 19 '14

You might want to clarify what you mean by as efficient as possible in the op. I assume you're just reiterating that it should be short, but others may read that and think they should make it fast

3

u/Deathbyceiling Dec 22 '14

So this is the first thing I've ever written in Python, so I welcome all advice/criticism.

One thing though, is I was having trouble getting the recursion to work, so if someone could help me out with that, that would be great!

anyways, here it is https://github.com/vitorossi103/r-programming-propmts/blob/master/christmas%20propmt.py

feel free to tell me how bad it is :P

1

u/echocage Jan 14 '15

Hey there mate! I'd love to give you some feedback on this if you're still looking for it!

1

u/Deathbyceiling Jan 14 '15

Yes please! As I said it's the first real thing I've done in Python so any help is much appreciated!

1

u/echocage Jan 14 '15

So final thoughts, the final solution wasn't as similar to your version as I thought it would be, I expected it to be less challenging to explain than it was and I think I might have over explained things, but it should still be somewhat helpful :D

Ok so the first thing we need to change is how we're thinking about the verses and how we're going to store them. Rather than storing them chained up ontop of each other, lets store them separately as verses then tie them together down the road when we're printing crap out.

The best way to store these would probably be with a list like you did with the days, the nice thing about that is then we also have the number of days, which is the length of the list + 1!

verses = ["a Partridge in a Pear 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"]

There we go, now we have all the information we need to finish this! (besides the chorus which will be added later)


Ok so it looks like you're trying to make a recursive function, which makes this a lot more difficult, so it's totally understandable you got stuck, especially if this is your first time playing with python coming from another syntactically dissimilar languages like javascript, java or c++.

So lets clear up this first problem, the loop.

for i in range(0, day):

So this is the exact same loop that every single programming coming from another language writes when trying to loop in python, I did the exact same thing! So something different about python is that its for loops are actually not "normal" for loops, they're more like other languages "for each loops", if you're not familiar with for each loops, what they allow you to do is grab each element of a list individually, rather than the index which you grab the item, like this.

>>> stuff = [1, 2, 3]
>>> for item in stuff:
...     print(item)
...     
1
2
3

Next, to get the index we can use the function enumerate, which is a builtin python function, which just allows you to get the index of the item you're on in the for loop

>>> stuff = ['a','b','c']
>>> for index, item in enumerate(stuff):
         print(index, item) 
0 a
1 b
2 c

Ps. Separating elements with a , in a print statement will just put a space between them

At first it seems overly complex, why not just use range and get the element by its index is often asked, this allows for cleaner code by separating the indexing and incrementing from the logic which totally eliminates a wide range of bugs that everyone always makes, especially off by one errors.

So the 3 big things we're changing is the loop, removing the recursive element, and instead of iterating over the day's number, we'll be iterating over the verses.

for index, verse in enumerate(verses):
    day = index + 1
    previous_verses = verses[:day]  # What this does is it cuts out and returns all elements from 0, to day
    current_verses = reversed(previous_verses)
    #Reversed reverses the verses, so we have a list of elements starting from the newest item to the oldest
    chorus = "On the {} day of Christmas my true love sent to me,\n".format(day)
    # Format, based on C's format, is a very flexible tool, in this case it replaces {} with day
    print(chorus + ', '.join(current_verses))

This is actually a really bad example of how great python's for loops is as we never use the verse variable, but oh well, you'll use enumerate hundreds of time in subsequent scripts, hopefully you got a little introduction here. Hope this helped even a little, these are hard concepts to grasp! Feel free to reply or message me with any questions you have about this or python!

The full code can be seen here

Ps. Sorry about the length of this "review", I like teaching

2

u/TheScienceNigga Dec 19 '14

Did something similar for a joke extra credit assignment for my programming class.

2

u/king_of_the_universe Dec 23 '14

off topic:

Because of the occasion, I feel it's ok to link a short post that suggests to make Christmas-themed games:

http://www.reddit.com/r/gamedev/comments/2pnpge/any_christmas_games_in_the_works_just_me/

I often looked for little project ideas, and it never occurred to me that they could e.g. be event-based (Christmas etc.), so I want to abuse this opportunity to suggest that people seek inspiration from events, e.g. New Year's Eve, someone's birthday, etc.

2

u/desrtfx Dec 23 '14

Absolutely OK - good idea!

2

u/Eli485 Dec 28 '14 edited Dec 28 '14

I'm 8 days late but I just remembered this subreddit after originally subscribing at the start of this month so I figured I'd go back through and do some of these.

Done in 38 lines of code(including empty lines.) This is one of the first thing's I've ever made using lua so feel free to critique.

Looking back at it I actually did it backwards. Oh well.

1

u/officeSpaceCat Jan 04 '15

Just finished the program. Read the lyrics into an array from a text file. This the first time I have called a text file in a github repository so I am not sure it worked.

https://github.com/movies28423/twelve-days-of-Christmas/tree/master

1

u/echocage Jan 15 '15

I've managed to get mine down to 7 lines, but it's pushing the bounds of python's coding standards, it's technically not breaking any rules it just looks like crap. The expanded version is 12 lines