In this exercise, you'll create a class to output the lyrics to the traditional English Christmas carol "The Twelve Days of Christmas" (complete lyrics below).
In this song, each verse is built on top of the previous verses in a repeating pattern. Can you use Ruby to build up the repeated lyrics programmatically?
Note on testing: Unlike previous exercises, this exercise doesn't include an extensive set of test cases. Instead, there is an "acceptance" test to make sure that the final output is correct. A file called song.txt
is included with the exercise, but this is to be used for the acceptance test to validate the solution, not as part of the solution itself.
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 Gold 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 Gold 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 Gold 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 Gold 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 Gold 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 Gold 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 Gold 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 Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
For installation and learning resources, refer to the Ruby resources page.
For running the tests provided, you will need the Minitest gem. Open a terminal window and run the following command to install minitest:
gem install minitest
If you would like color output, you can require 'minitest/pride'
in
the test file, or note the alternative instruction, below, for running
the test file.
Run the tests from the exercise directory using the following command:
ruby twelve_days_test.rb
To include color from the command line:
ruby -r minitest/pride twelve_days_test.rb
Wikipedia http://en.wikipedia.org/wiki/The_Twelve_Days_of_Christmas_(song)
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
require 'minitest/autorun'
require_relative 'twelve_days'
class TwelveDaysTest < Minitest::Test
def test_the_whole_song
song_file = File.expand_path('../song.txt', __FILE__)
expected = IO.read(song_file)
assert_equal expected, TwelveDays.song
end
end
class TwelveDays
GIFTS = {
'first': "a Partridge in a Pear Tree.\n",
'second': 'two Turtle Doves',
'third': 'three French Hens',
'fourth': 'four Calling Birds',
'fifth': 'five Gold Rings',
'sixth': 'six Geese-a-Laying',
'seventh': 'seven Swans-a-Swimming',
'eighth': 'eight Maids-a-Milking',
'ninth': 'nine Ladies Dancing',
'tenth': 'ten Lords-a-Leaping',
'eleventh': 'eleven Pipers Piping',
'twelfth': 'twelve Drummers Drumming'
}.freeze
def self.song
new.sing
end
def sing
day_names
.map do |day_name|
state_day(day_name) + list_gifts(day_name)
.push(first_day(day_name))
.join(', ')
end
.join("\n")
end
def day_names
GIFTS.keys
end
def state_day(day)
"On the #{day} day of Christmas my true love gave to me: "
end
def list_gifts(day_name)
day_names[1..day_names.find_index(day_name)]
.reverse
.map { |day_name| GIFTS[day_name] }
end
def first_day(day_name)
('and ' unless day_name == :first).to_s + GIFTS[:first]
end
end
A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.
Here are some questions to help you reflect on this solution and learn the most from it.
Level up your programming skills with 3,450 exercises across 52 languages, and insightful discussion with our volunteer team of welcoming mentors. Exercism is 100% free forever.
Sign up Learn More
Community comments