Skip to content

Instantly share code, notes, and snippets.

@kipcole9
Last active June 2, 2020 19:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kipcole9/2617b5966cd6cf40210bacaa0c5c7d1d to your computer and use it in GitHub Desktop.
Save kipcole9/2617b5966cd6cf40210bacaa0c5c7d1d to your computer and use it in GitHub Desktop.
Elixir implementation of pig latin translation
defmodule PigLatin do
# vowels: a, e, i, o, u, y_, x_
@vowels ["a", "e", "i", "o", "u"]
# special constants: "ch", "qu", "squ", "th", "thr", "sch"
@special ["ch", "qu", "squ", "thr", "th", "sch"]
@ay "ay"
defguard is_vowel(c) when c in @vowels
defguard not_vowel(c) when c not in @vowels
defguard is_special(c) when c in @special
@doc """
Given a `phrase`, translate it a word at a time to Pig Latin.
* Words beginning with consonants should have the consonant moved to the end of
the word, followed by "ay".
* Words beginning with vowels (aeiou) should have "ay" added to the end of the
word.
* Some groups of letters are treated like consonants, including "ch", "qu",
"squ", "th", "thr", and "sch".
* Some groups are treated like vowels, including "yt" and "xr".
"""
@spec translate(phrase :: String.t()) :: String.t()
def translate(phrase) do
phrase
|> String.split()
|> Enum.map(&parse_string/1)
|> Enum.join(" ")
end
# Cases vowels
def parse_string(<<char::binary-1, _rest::binary>> = word)
when is_vowel(char),
do: word <> "ay"
# 'x' and 'y', when followed by a consonant, are treated like a vowel
def parse_string(<<first::binary-1, char::binary-1, _rest::binary>> = word)
when first in ["y", "x"] and not_vowel(char),
do: word <> @ay
# Constants
def parse_string(<<special::binary-3, rest::binary>>)
when is_special(special),
do: rest <> special <> @ay
def parse_string(<<special::binary-2, rest::binary>>)
when is_special(special),
do: rest <> special <> @ay
# case starting with unknown number of constants (but not special constants)
def parse_string(other) do
{leading_consonants, vowel_part} = split_at_first_vowel(other)
vowel_part <> leading_consonants <> @ay
end
defp split_at_first_vowel(word, leading_consonants \\ "")
defp split_at_first_vowel(<<char::binary-1, rest::binary>>, leading_consonants)
when not_vowel(char),
do: split_at_first_vowel(rest, leading_consonants <> char)
defp split_at_first_vowel(vowel_part, leading_consonants),
do: {leading_consonants, vowel_part}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment