Daily Challenge #22 - Simple Pig Latin

thepracticaldev profile image dev.to staff ・1 min read

The goal of today's challenge is to translate English into Pig Latin. This challenge comes from user2505876 on CodeWars.

Write a function that moves the first letter of each word to the end of the word, then add "ay". Leave punctuation untouched.

pig_it('Pig latin is cool') # igPay atinlay siay oolcay
pig_it('Hello world !') # elloHay orldway !

This one is somewhat tricky. I bet it would be even harder to turn Pig Latin back to English, I'd love to see someone try it~!

Oodgay ucklay, appyhay odingcay!

Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge for a future post? Email yo+challenge@dev.to with your suggestions!

Posted on by:

thepracticaldev profile

dev.to staff


The hardworking team behind dev.to ❤️


markdown guide

CSS (kind of)

Separate the words in <span>s, and add the class "piglatin" to the container.

.piglatin span {
  display: inline-block;
  position: relative;
  margin-right: 1em;

.piglatin span::first-letter {
  float: right;

.piglatin span::after {
  content: "ay";
  position: absolute;
  left: 100%;

The idea is based on floating the first letter to the right using the pseudo-class :first-letter, and then adding "ay" using the pseudo-element ::after... although it doesn't work well with punctuation :-/

You can see a demo running on CodePen:


Screen readers still read the sentences right, even when visually they are in pig latin.


So happy to see another CSS solution! It's been awhile lol

Hell of a job!


Yes. The last ones have been impossible. But 4-5 out of 22 is not that bad :P


Here goes a JavaScript oneliner

const pigIt = (s) => s.split(' ').map(e=>e.match(/\w/)?`${e.slice(1)}${e[0]}ay`:e).join(' ')
pigIt('Pig Latin is cool');
"igPay atinLay siay oolcay"

pigIt('Hello world !');
"elloHay orldway !"

And just for fun, an unPigIt oneliner too!

const unPigIt = (s) => s.split(' ').map(e=>e.match(/\w/)?e[e.length-3]+e.slice(0,-3):e).join(' ')

unPigIt('igPay atinLay siay oolcay');
"Pig Latin is cool"

unPigIt('elloHay orldway !');
"Hello world !"

Perl one-liner as well

say join(" ", map { s/(\w)(\w+)/\2\1ay/r } split /\s/, "Pig latin is cool")

#igPay atinlay siay oolcay

This one handles leaving punctuation alone, so this would work as well:

say join(" ", map { s/(\w)(\w+)/\2\1ay/r } split /\s/, '"Pig" latin is cool')

#"igPay" atinlay siay oolcay

No need to split and join:

say '"Pig" latin is cool' =~ s/(\w)(\w+)/$2$1ay/gr;

python one liner ftw.

print(*map(lambda x: f'{x[1:]+x[0]}ay' if x.isalpha() else x, input().split()))
>>> print(*map(lambda x: f'{x[1:]+x[0]}ay' if x.isalpha() else x, input().split()))
Pig latin is cool
igPay atinlay siay oolcay

Ruby 2.6

require "minitest/autorun"

class PigLatinTranslator
  LATINATOR = -> (word) { word =~ /\w/ ? "#{word[1..-1]}#{word[0]}ay" : word }

  def self.translate sentence
    sentence.split(' ').map(&LATINATOR).join(' ')

class PigLatinTranslatorTest < MiniTest::Test
  def test_sentence_without_punctuation
    translated_sentence = PigLatinTranslator.translate("Pig latin is cool")

    assert_equal "igPay atinlay siay oolcay", translated_sentence

  def test_sentence_with_punctuation
    translated_sentence = PigLatinTranslator.translate("Hello world !")

    assert_equal "elloHay orldway !", translated_sentence

Here is the simple solution with Python:

def pig_it(text):
    answer = ""
    pig_prefix = "ay"

    text_list = text.split(' ')

    for text in text_list:
        first_text = text[0]

        start_index = 1
        if len(text) == 0:
            start_index = 0

        if first_text == "?" or first_text == "!" or first_text == "," or first_text == ".":
            answer += text
            answer += text[start_index:] + first_text + pig_prefix + " " 

    if answer[-1] == " ":
        return answer[0:-1]

    return answer


defmodule PigLatin do
  def pig_it(input) do
    |> String.split()
    |> Enum.map(&latinate/1)
    |> Enum.join(" ")

  defp latinate(<<first_letter::binary-size(1), rest::binary>>),
    do: rest <> first_letter <> "ay"

Rust Solution!

I paid specific attention to the punctuation rule, and made sure to get that right!

I also wasn't satisfied with just the example punctuation because nobody spaces out their punctuation like that ! See doesn't that look weird ?
Also the spec doesn't mention at all with how to treat words with punctuation IN them! So I made my own spec here and decided to split the words on any punctuation, and treat each side as it own word. Proper pig latin? Maybe not! But it's doing what I intended!

fn pigify_word(word: &str) -> String {
    println!("{}", word);
    if word.chars().all(|x| x.is_alphanumeric()) {
        let mut chars = word.chars();
        let first_letter = chars.next().unwrap();
        let rest_of_letters: String = chars.collect();

        format!("{}{}ay", rest_of_letters, first_letter)
    } else if word.chars().all(|x| !x.is_alphanumeric()) {
    } else {
        let symbol_index = word.find(|c: char| !c.is_alphanumeric()).unwrap();
        let alphanumeric_index = word.find(|c: char| c.is_alphanumeric()).unwrap();

        let index = symbol_index.max(alphanumeric_index);

        [word[0..index].to_string(), word[index..].to_string()]
            .map(|x| pigify_word(x))

pub fn pig_it(english_input: &str) -> String {
        .split(" ")
        .join(" ")

mod tests {
    use crate::*;

    fn it_works_without_punctuation() {
            pig_it("Pig latin is cool"),
            "igPay atinlay siay oolcay".to_string()

    fn it_works_with_spaced_out_punctuation() {
        assert_eq!(pig_it("Hello world !"), "elloHay orldway !".to_string());

    fn it_works_with_word_ending_punctuation() {
            pig_it("Hello world! How is it going today?"),
            "elloHay orldway! owHay siay tiay oinggay odaytay?".to_string()

    fn it_works_with_word_mid_punctuation() {
            pig_it("Hello world! How's it going today?"),
            "elloHay orldway! owHay'say tiay oinggay odaytay?".to_string()

const vowels = ['a','i','e','o','u'];
// checkVowels :: String -> Bool
const checkVowel = str => vowels.includes(str.charAt(0))
// translate:: String -> String
const translate = str => checkVowel(str)? str + 'way ' : str.substring(1,str.length)+ str.charAt(0) + 'ay'
// pigLatin :: String -> [String] -> String  
const pigLatin = str => str.split(' ').map(word => translate(word)).join(" ")

Your pig latin rules are incorrect in the Examples. Words beginning with vowels do not move the first letter and traditionally end in 'way'. So pig_it('Pig latin is cool') should be # igPay atinlay isway oolcay