Pig Latin Pt II

Clarification

In the previous post, I’d said I thought that the reason split_consonants had split in such a way that the consonants were in the first part of the split and the vowels were in the second was because the only words that would have made use of the variables created by split_consonants would be words that started with consonants. After playing around with IO.inspect() on the vowel and consonant variables given different input, I believe that to be the case.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
defmodule PigLatin do
def piglify(word) do
first_char = String.at(word, 0)
second_char = String.at(word, 1)

split_consonants =
Regex.split(~r/([aeio]|(?<!q)u)(.*)/, word,
trim: true,
parts: 2,
include_captures: true
)

consonant = Enum.at(split_consonants, 0)
vowel = Enum.at(split_consonants, 1) || ""
IO.inspect("consonant " <> consonant)
IO.inspect("vowel " <> vowel)
cond do
String.match?(first_char, ~r/[aeio]|(?<!q)u/) ->
word <> "ay"

String.match?(first_char, ~r/y|x/) && !String.match?(second_char, ~r/[aeio]|(?<!q)u/) ->
word <> "ay"

true ->
vowel <> consonant <> "ay"
end
end
end

tests = Enum.map(["yttria", "over", "under", "why", "whatever", "whichever", "aquaduct", "dhdh", "square"], fn x -> PigLatin.piglify(x) end)

IO.inspect(tests)

The resturn from this function is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"consonant yttr"
"vowel ia"
"consonant over"
"vowel "
"consonant under"
"vowel "
"consonant why"
"vowel "
"consonant wh"
"vowel atever"
"consonant wh"
"vowel ichever"
"consonant aquaduct"
"vowel "
"consonant dhdh"
"vowel "
"consonant squ"
"vowel are"
["yttriaay", "overay", "underay", "whyay", "ateverwhay", "icheverwhay",
"aquaductay", "dhdhay", "aresquay"]

The Refactor!

So I realized that since two of my conditionals evaluated to the same thing, I decided to combine them into one condition:

Original:

1
2
3
4
5
String.match?(first_char, ~r/[aeio]|(?<!q)u/) ->
word <> "ay"

String.match?(first_char, ~r/y|x/) && !String.match?(second_char, ~r/[aeio]|(?<!q)u/) ->
word <> "ay"

Refactor:

1
2
3
String.match?(first_char, ~r/[aeio]|(?<!q)u/) or
(String.match?(first_char, ~r/y|x/) && !String.match?(second_char, ~r/[aeio]|(?<!q)u/)) ->
word <> "ay"

Another change I ended up making was to clean up the translate function. Since I’m passing the words argument into successive functions, I don’t actually need to name the variable – I could just use the pipe operator to pass it into the next function in the sequence:

Original:

1
2
3
4
5
6
def translate(phrase) do
words = String.split(phrase, " ", trim: true)

Enum.map(words, fn x -> piglify(x) end)
|> Enum.join(" ")
end

Refactor:

1
2
3
4
5
def translate(phrase) do
String.split(phrase, " ", trim: true)
|> Enum.map(fn x -> piglify(x) end)
|> Enum.join(" ")
end

The refactored program, then, becomes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
defmodule PigLatin do
@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
String.split(phrase, " ", trim: true)
|> Enum.map(fn x -> piglify(x) end)
|> Enum.join(" ")
end

def piglify(word) do
first_char = String.at(word, 0)
second_char = String.at(word, 1)

split_consonants =
Regex.split(~r/([aeio]|(?<!q)u)(.*)/, word,
trim: true,
parts: 2,
include_captures: true
)

consonant = Enum.at(split_consonants, 0)
vowel = Enum.at(split_consonants, 1)

cond do
String.match?(first_char, ~r/[aeio]|(?<!q)u/) or
(String.match?(first_char, ~r/y|x/) && !String.match?(second_char, ~r/[aeio]|(?<!q)u/)) ->
word <> "ay"

true ->
vowel <> consonant <> "ay"
end
end
end

Short post today because I woke up early to watch the in-flight abort test for Space-X and I spent the day watching the Liverpool FC game, a hockey game, the Kansas City Chiefs game, and now the Packers game – and I am tired.

Catch ya later!

- Amy