Day 5: Doesn’t He Have Intern-Elves For This?
Mix.install([{:kino, "~> 0.8.0"}])
Input
input = Kino.Input.textarea("Please paste your input:")
defmodule Day5Shared do
def parse(input) do
input
|> Kino.Input.read()
|> String.split("\n")
end
end
Part 1
Santa needs help figuring out which strings in his text file are naughty or nice.
A nice string is one with all of the following properties:
-
It contains at least three vowels (
aeiou
only), likeaei
,xazegov
, oraeiouaeiouaeiou
. -
It contains at least one letter that appears twice in a row, like
xx
,abcdde
(dd
), oraabbccdd
(aa
,bb
,cc
, ordd
). -
It does not contain the strings
ab
,cd
,pq
, orxy
, even if they are part of one of the other requirements.
For example:
-
ugknbfddgicrmopn
is nice because it has at least three vowels (u...i...o...
), a double letter (...dd...
), and none of the disallowed substrings. -
aaa
is nice because it has at least three vowels and a double letter, even though the letters used by different rules overlap. -
jchzalrnumimnmhp
is naughty because it has no double letter. -
haegwjzuvuyypxyu
is naughty because it contains the stringxy
. -
dvszwmarrgswjxmb
is naughty because it contains only one vowel.
How many strings are nice?
defmodule Day5Part1 do
def classify(string),
do: if(nice?(string), do: :nice, else: :naughty)
defp nice?(string) do
vowels = Regex.scan(~r/[aeiou]/, string)
double_trouble = Regex.scan(~r/(.)\1/, string)
naughty_pairs = Regex.scan(~r/ab|cd|pq|xy/, string)
length(vowels) >= 3 and length(double_trouble) >= 1 and length(naughty_pairs) == 0
end
end
input
|> Day5Shared.parse()
|> Enum.map(&Day5Part1.classify/1)
|> Enum.count(&(&1 == :nice))
Part 2
Realizing the error of his ways, Santa has switched to a better model of determining whether a string is naughty or nice. None of the old rules apply, as they are all clearly ridiculous.
Now, a nice string is one with all of the following properties:
-
It contains a pair of any two letters that appears at least twice in the string without overlapping, like
xyxy
(xy
) oraabcdefgaa
(aa
), but not likeaaa
(aa
, but it overlaps). -
It contains at least one letter which repeats with exactly one letter between them, like
xyx
,abcdefeghi
(efe
), or evenaaa
.
For example:
-
qjhvhtzxzqqjkmpb
is nice because is has a pair that appears twice (qj
) and a letter that repeats with exactly one letter between them (zxz
). -
xxyxx
is nice because it has a pair that appears twice and a letter that repeats with one between, even though the letters used by each rule overlap. -
uurcxstgmygtbstg
is naughty because it has a pair (tg
) but no repeat with a single letter between them. -
ieodomkazucvgmuy
is naughty because it has a repeating letter with one between (odo
), but no pair that appears twice.
How many strings are nice under these new rules?
defmodule Day5Part2 do
def classify(string) do
# again, let's use back-references, read more about back-references:
# https://medium.com/rubycademy/3-ways-to-use-regexp-capture-groups-with-back-references-in-ruby-b4969cc9b3ec
has_pairs? = Regex.match?(~r/([a-z][a-z]).*\1/, string)
has_litms? = Regex.match?(~r/([a-z])[a-z]\1/, string)
if has_pairs? and has_litms? do
:nice
else
:naughty
end
end
end
input
|> Day5Shared.parse()
|> Enum.map(&Day5Part2.classify/1)
|> Enum.count(&(&1 == :nice))