Last active
June 2, 2020 19:50
-
-
Save kipcole9/2617b5966cd6cf40210bacaa0c5c7d1d to your computer and use it in GitHub Desktop.
Elixir implementation of pig latin translation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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