Avatar of reflection

reflection's solution

to Pig Latin in the Kotlin Track

Published at Oct 08 2019 · 0 comments
Test suite

Implement a program that translates from English to Pig Latin.

Pig Latin is a made-up children's language that's intended to be confusing. It obeys a few simple rules (below), but when it's spoken quickly it's really difficult for non-children (and non-native speakers) to understand.

  • Rule 1: If a word begins with a vowel sound, add an "ay" sound to the end of the word. Please note that "xr" and "yt" at the beginning of a word make vowel sounds (e.g. "xray" -> "xrayay", "yttria" -> "yttriaay").
  • Rule 2: If a word begins with a consonant sound, move it to the end of the word and then add an "ay" sound to the end of the word. Consonant sounds can be made up of multiple consonants, a.k.a. a consonant cluster (e.g. "chair" -> "airchay").
  • Rule 3: If a word starts with a consonant sound followed by "qu", move it to the end of the word, and then add an "ay" sound to the end of the word (e.g. "square" -> "aresquay").
  • Rule 4: If a word contains a "y" after a consonant cluster or as the second letter in a two letter word it makes a vowel sound (e.g. "rhythm" -> "ythmrhay", "my" -> "ymay").

There are a few more rules for edge cases, and there are regional variants too.

See http://en.wikipedia.org/wiki/Pig_latin for more details.


Go through the setup instructions for Kotlin to install the necessary dependencies:


Making the test suite pass

Execute the tests with:

$ gradlew test

Use gradlew.bat if you're on Windows

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by removing the @Ignore annotation.


The Pig Latin exercise at Test First Teaching by Ultrasaurus https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.


import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import kotlin.test.assertEquals

class PigLatinTest(val input: String, val expectedOutput: String) {

    companion object {
        @Parameterized.Parameters(name = "{index}: translate({0})={1}")
        fun data() = arrayOf(
                // Ay is added to words that start with vowels
                arrayOf("apple",  "appleay"),
                arrayOf("ear",    "earay"),
                arrayOf("igloo",  "iglooay"),
                arrayOf("object", "objectay"),
                arrayOf("under",  "underay"),

                // Ay is added to words that start with vowels followed by qu
                arrayOf("equal",  "equalay"),

                // First letter and ay are moved to the end of words that start with consonants
                arrayOf("pig",    "igpay"),
                arrayOf("koala",  "oalakay"),
                arrayOf("xenon",  "enonxay"),
                arrayOf("qat",    "atqay"),

                // Ch is treated like a single consonant
                arrayOf("chair", "airchay"),

                // Qu is treated like a single consonant
                arrayOf("queen", "eenquay"),

                // Qu and a single preceding consonant are treated like a single consonant
                arrayOf("square", "aresquay"),

                // Th is treated like a single consonant
                arrayOf("therapy", "erapythay"),

                // Thr is treated like a single consonant
                arrayOf("thrush", "ushthray"),

                // Sch is treated like a single consonant
                arrayOf("school", "oolschay"),

                // Yt is treated like a single vowel
                arrayOf("yttria", "yttriaay"),

                // Xr is treated like a single vowel
                arrayOf("xray", "xrayay"),

                // Y is treated like a consonant at the beginning of a word
                arrayOf("yellow", "ellowyay"),

                // Y is treated like a vowel at the end of a consonant cluster
                arrayOf("rhythm", "ythmrhay"),

                // Y as second letter in two letter word
                arrayOf("my",     "ymay"),

                // Phrases are translated
                arrayOf("quick fast run", "ickquay astfay unray")

    fun test() {
        assertEquals(expectedOutput, PigLatin.translate(input))

object PigLatin {

    private val vowels = listOf('a', 'e', 'i', 'o', 'u')
    private val vowelSounds = listOf("a", "e", "i", "o", "u", "xr", "yt")

    fun translate(input: String): String {
        return input.split(" ").map {
        }.joinToString(" ")

    private fun translateWord(input: String): String {
        return if (this.vowelSounds.any { input.startsWith(it, ignoreCase = true) }) {
            input + "ay"
        } else {
            val firstVowel = indexOfFirstVowelSound(input)
            if (firstVowel > 0) {
                input.substring(firstVowel) + input.substring(0, firstVowel) + "ay"
            } else {
                val yIndex = input.indexOf('y')
                input.substring(yIndex) + input.substring(0, yIndex) + "ay"

     * Precondition: input does NOT start with a vowel, otherwise an Exception is thrown
    private fun indexOfFirstVowelSound(input: String): Int {
        input.forEachIndexed { i, c ->
            if (c in this.vowels && !(c.equals('u') && input[i - 1].equals('q', ignoreCase = true))) {
                return i
        return -1


Community comments

Find this solution interesting? Ask the author a question to learn more.

What can you learn from this solution?

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.

  • What compromises have been made?
  • Are there new concepts here that you could read more about to improve your understanding?