I've just complete a Pig Latin translator as a code kata and I was hoping someone would review it for me.
Here is the kata:
PigLatin Kata
Create a PigLatin class that is initialized with a string
- detail: The string is a list of words separated by spaces: 'hello world'
- detail: The string is accessed by a method named phrase
- detail: The string can be reset at any time without re-initializing
- example: PigLatin.new('hello world')
completed (Y|n):
Translate Method
Create a translate method that translates the phrase from english to pig-latin.
- detail: The method will return a string.
- detail: The empty string will return nil.
- example: "" translates to nil
completed (Y|n):
Translate words that start with vowels.
- detail: Append "ay" to the word if it ends in a consonant.
- example: "ask" translates to "askay"
- detail: Append "yay" to the word if it ends with a vowel.
- example: "apple" translates to "appleyay"
- detail: Append "nay" to the word if it ends with "y".
- example: "any" translates to "anynay"
completed (Y|n):
Translate a word that starts with a single consonant.
- detail: Removing the consonant from the front of the word.
- detail: Add the consonant to the end of the word.
- detail: Append 'ay' to the resulting word.
- example: "hello" translates to "ellohay"
- example: "world" translates to "orldway"
completed (Y|n):
Translate words that start with multiple consonants.
- detail: Remove all leading consonants from the front of the word.
- detail: Add the consonants to the end of the word.
- detail: Append 'ay' to the resulting word.
- example: "known" translates to "ownknay"
- example: "special" translates to "ecialspay"
completed (Y|n):
Support any number of words in the phrase.
- example: "hello world" translates to "ellohay orldway"
- detail: Each component of a hyphenated word is translated seperately.
- example: "well-being" translates to "ellway-eingbay"
completed (Y|n):
Support capital letters.
- detail: If a word is captalized, the translated word should be capitalized.
- example: "Bill" translates to "Illbay"
- example: "Andrew" translates to "Andreway"
completed (Y|n):
Retain punctuation.
- detail: Punctuation marks should be retained from the source to the translated string
- example: "fantastic!" tranlates to "anfasticfay!"
- example: "Three things: one, two, three." translates to "Eethray ingsthay: oneyay, otway, eethray."
completed (Y|n):
Congratulations!
- Create a PigLatin class that is initialized with a string 00:12:52
- Create a translate method that translates the phrase from english to p 00:03:00
- Translate words that start with vowels. 00:08:56
- Translate a word that starts with a single consonant. 00:04:32
- Translate words that start with multiple consonants. 00:08:08
- Support any number of words in the phrase. 00:25:19
- Support capital letters. 00:05:05
- Retain punctuation. 00:17:00
----------------------------------------------------------------------
Total Time taking PigLatin kata: 01:24:52
And my specs:
require 'spec_helper'
require 'piglatin'
describe PigLatin do
let(:pig_latin) { PigLatin.new(string) }
let(:string) { "hello world" }
describe "new" do
specify { expect { pig_latin }.to_not raise_error }
end
describe ".phrase" do
subject { pig_latin.phrase }
it { should eq("hello world") }
it "can reset the phrase" do
pig_latin
pig_latin.phrase = "world hello"
subject.should eq("world hello")
end
end
describe ".translate" do
subject { pig_latin.translate }
its(:class) { should eq(String) }
context "empty string" do
let(:string) { "" }
it { should eq(nil) }
end
context "words that start with vowels" do
let(:string) { "ask" }
it { should eq("askay") }
context "and also ends with a vowel" do
let(:string) { "apple" }
it { should eq("appleyay") }
end
context "and ends with y" do
let(:string) { "any" }
it { should eq("anynay") }
end
end
context "words that start with a single consonant" do
let(:string) { "hello" }
it { should eq("ellohay") }
end
context "words that start with multiple consonants" do
context "known" do
let(:string) { "known" }
it { should eq("ownknay") }
end
context "special" do
let(:string) { "special" }
it { should eq("ecialspay") }
end
end
context "multiple words" do
let(:string) { "hello world" }
it { should eq("ellohay orldway") }
context "hyphenated words" do
let(:string) { "well-being" }
it { should eq("ellway-eingbay") }
end
end
context "Capitalization" do
context "Bill" do
let(:string) { "Bill" }
it { should eq("Illbay") }
end
context "Andrew" do
let(:string) { "Andrew" }
it { should eq("Andreway") }
end
end
context "Retain Punctuation" do
context "fantastic!" do
let(:string) { "fantastic!" }
it { should eq("antasticfay!") }
end
context "Three things: one, two, three." do
let(:string) { "Three things: one, two, three." }
it { should eq("Eethray ingsthay: oneyay, otway, eethray.") }
end
end
end
end
And, finally, the PigLatin
class:
class PigLatin
attr_accessor :phrase
def phrase=(string)
@phrase = string
end
alias :initialize :phrase=
def translate
return nil if (@phrase.empty?)
word_array = @phrase.split(/\s/)
word_array.collect! do |word|
translate_word(word)
end
translated_phrase = word_array.join(" ")
return translated_phrase
end
private
def translate_word word
words = word.split("-")
words.collect! do |word|
punctuation = word.slice!(/\W/)
if (word[0] =~ /[aeiou]/i)
case word[-1]
when /[aeiou]/
word += "yay"
when /y/
word += "nay"
else
word += "ay"
end
else
consonants = word.slice!(/^[^aeiou]*/)
word.capitalize! if (consonants.downcase!)
word += consonants + "ay"
end
if (punctuation)
word << punctuation
end
word
end
return words.join("-")
end
end