Solving Single Word Pig Latin in Java


The challenge

Pig Latin is an English language game where the goal is to hide the meaning of a word from people not aware of the rules.

So, the goal of this challenge is to write a function that encodes a single word string to pig latin.

The rules themselves are rather easy:

  1. The word starts with a vowel(a,e,i,o,u) -> return the original string plus “way”.

  2. The word starts with a consonant -> move consonants from the beginning of the word to the end of the word until the first vowel, then return it plus “ay”.

  3. The result must be lowercase, regardless of the case of the input. If the input string has any non-alpha characters, the function must return None, null, Nothing (depending on the language).

  4. The function must also handle simple random strings and not just English words.

  5. The input string has no vowels -> return the original string plus “ay”.

For example, the word “spaghetti” becomes “aghettispay” because the first two letters (“sp”) are consonants, so they are moved to the end of the string and “ay” is appended.

The solution in Java code

Option 1:

import java.util.Arrays;
import java.util.List;

public class PigLatin {

    private List<String> vowels = Arrays.asList(new String[]{"a", "e", "i", "0", "u"});

    public String translate(String str) {

        str = str.toLowerCase();

        if (hasNonAlphaChar(str)) {
            return null;
        }

        if(hasNoVowels(str)){
            return str + "ay";
        }

        if (startsWithAVowel(str)) {
            return str + "way";
        }

        do {
            str = moveFirstLetterToTheEnd(str);
        } while (startsWithAConsonant(str));

        return str + "ay";
    }

    private String moveFirstLetterToTheEnd(String str) {
        return str.substring(1) + str.substring(0, 1);
    }

    private boolean hasNoVowels(String str) {
        return str.chars().mapToObj(c -> Character.toString((char) c)).noneMatch(vowels::contains);
    }

    private boolean hasNonAlphaChar(String str) {
        return str.toLowerCase().chars().anyMatch(value -> value < 97 || value > 122);
    }

    private boolean startsWithAVowel(String str) {
        return vowels.contains(str.toLowerCase().substring(0, 1));
    }

    private boolean startsWithAConsonant(String str) {
        return !startsWithAVowel(str);
    }
}

Option 2:

class PigLatin {
  static String translate(String s) {
    return (s = s.toLowerCase()).matches("[aeiou][a-z]*") ? s + "way" : s.matches("[a-z]*") ? s.replaceAll("^([^aeiou]*)(.*)","$2$1ay") : null;
  }
}

Option 3:

public class PigLatin{
 
   public String translate(String str){
        str = str.toLowerCase();
        if (str.matches("(.)*[^a-z](.)*"))
            return null;
        if (str.substring(0,1).matches("[aeiou]"))
            return str + "way";
        if (str.matches("(.)*[aeiou](.)*"))
            while (!(str.substring(0, 1).matches("[aeiou]")))
                str = str.substring(1) + str.charAt(0);
        return str + "ay";
   }
   
}

Test cases to validate our solution

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;


public class TestPigLatin {

	private PigLatin p;

	@Before
	public void setUp() throws Exception {
		p = new PigLatin();
		
	}

	@Test
	public void testMap() {
		assertEquals("apmay", p.translate("map"));
	}
	
	@Test
	public void testegg() {
		assertEquals("eggway", p.translate("egg"));
	}
  
  @Test
	public void testspaghetti() {
		assertEquals("aghettispay", p.translate("spaghetti"));
	}
}