Day 5: Doesn’t He Have Intern-Elves For This?
Mix.install([
{:kino, "~> 0.12.3"}
])
Modules
defmodule NiceStrings do
@moduledoc """
Functions for identifying nice strings.
"""
@typedoc "The ruleset used to identify nice strings"
@type rules :: :part1 | :part2
@doc """
Counts the number of strings that are "nice" according to a specified
ruleset.
## Examples
```elixir
iex> ["ugknbfddgicrmopn", "jchzalrnumimnmhp", "aaa"]
iex> |> NiceStrings.count(:part1)
2
iex> ["qjhvhtzxzqqjkmpb", "ieodomkazucvgmuy", "uurcxstgmygtbstg"]
iex> |> NiceStrings.count(:part2)
1
```
"""
@spec count(list(String.t()), rules()) :: non_neg_integer()
def count(strings, rules) do
strings
|> Enum.count(&nice_string?(&1, rules))
end
# validates if string is nice
defp nice_string?(str, rules)
# using rules for part 1
defp nice_string?(str, :part1) do
contains_three_vowels?(str) and
contains_double_letter?(str) and
not contains_illegal_substring?(str)
end
# using rules for part 2
defp nice_string?(str, :part2) do
contains_pair_twice?(str) and
contains_repeat_with_letter_between?(str)
end
# does the string have three vowels? using "a", "e", "i", "o" or "u"
defp contains_three_vowels?(str), do: String.match?(str, ~r/(.*(a|e|i|o|u).*){3}/)
# does the string contain a repeating letter consecutively? eg. "aa" or "pp"
defp contains_double_letter?(str), do: String.match?(str, ~r/(\w)\1/)
# does the string contain an illegal substring? "ab", "cd", "pq" or "xy"
defp contains_illegal_substring?(str), do: String.match?(str, ~r/(ab|cd|pq|xy)/)
# does the string contain the same pair of letters twice? eg. "rfaaiotaa" does
defp contains_pair_twice?(str), do: String.match?(str, ~r/(\w\w).*(\1)/)
# does the string contain a substring like "rtr" or "zxz" or "lgl"
defp contains_repeat_with_letter_between?(str), do: String.match?(str, ~r/(\w)\w(\1)/)
end
Input
input = Kino.Input.textarea("Please paste your puzzle input:")
Part 1
input
|> Kino.Input.read()
|> String.split("\n")
|> NiceStrings.count(:part1)
Part 2
input
|> Kino.Input.read()
|> String.split("\n")
|> NiceStrings.count(:part2)