Daily Challenge #22 - Simple Pig Latin

dev.to staff on July 23, 2019

The goal of today's challenge is to translate English into Pig Latin. This challenge comes from user2505876 on CodeWars. Write a function that mo... [Read Full]
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
 
 

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(' ')
  end
end

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
  end

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

    assert_equal "elloHay orldway !", translated_sentence
  end
end
 

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()) {
        word.to_string()
    } 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()]
            .iter()
            .map(|x| pigify_word(x))
            .collect()
    }
}

pub fn pig_it(english_input: &str) -> String {
    english_input
        .split(" ")
        .map(pigify_word)
        .collect::<Vec<_>>()
        .join(" ")
}

#[cfg(test)]
mod tests {
    use crate::*;

    #[test]
    fn it_works_without_punctuation() {
        assert_eq!(
            pig_it("Pig latin is cool"),
            "igPay atinlay siay oolcay".to_string()
        );
    }

    #[test]
    fn it_works_with_spaced_out_punctuation() {
        assert_eq!(pig_it("Hello world !"), "elloHay orldway !".to_string());
    }

    #[test]
    fn it_works_with_word_ending_punctuation() {
        assert_eq!(
            pig_it("Hello world! How is it going today?"),
            "elloHay orldway! owHay siay tiay oinggay odaytay?".to_string()
        );
    }

    #[test]
    fn it_works_with_word_mid_punctuation() {
        assert_eq!(
            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(" ")
 

Elixir:

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

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

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

code of conduct - report abuse