-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday5.exs
More file actions
76 lines (64 loc) · 2.39 KB
/
day5.exs
File metadata and controls
76 lines (64 loc) · 2.39 KB
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
defmodule Day5 do
# Part 2 functions
def how_many_nice_part_2(words) do
Enum.reduce(words, 0, fn (word, count) ->
count + (if naughty_or_nice_part_2(word) == :nice, do: 1, else: 0)
end)
end
def naughty_or_nice_part_2(word) do
if has_two_letters_repeating_twice?(word) && repeats_with_one_letter_between?(word), do: :nice, else: :naughty
end
def has_two_letters_repeating_twice?(word) do
prepared_word = remove_exactly_three_in_a_row(word)
all_pairs = Enum.chunk(prepared_word, 2) ++ Enum.chunk(tl(prepared_word), 2)
length(Enum.uniq(all_pairs)) < length(all_pairs)
end
defp remove_exactly_three_in_a_row([h | rest = [h2 | [h3 | [ h4 | _]]]], previous \\ '') do
if h == h2 && h == h3 && h != h4 && h != previous do
remove_exactly_three_in_a_row(rest, h)
else
[h | remove_exactly_three_in_a_row(rest, h)]
end
end
defp remove_exactly_three_in_a_row(rest = [h, h2, h3], previous), do: if h == h2 && h == h3 && h != previous, do: [h, h], else: rest
defp remove_exactly_three_in_a_row(rest, previous), do: rest
defp repeats_with_one_letter_between?(word) do
if length(word) < 3 do
false
else
Enum.zip(word, tl(word))
|> Enum.zip(word |> tl |> tl)
|> Enum.map(fn {{x, y}, z} -> [x, y, z] end)
|> Enum.any?(fn [first, _, last] -> first == last end)
end
end
# Part 1 functions
def how_many_nice(words) do
Enum.reduce(words, 0, fn (word, count) ->
count + (if naughty_or_nice(word) == :nice, do: 1, else: 0)
end)
end
defp naughty_or_nice(word) do
if has_three_vowels?(word) && has_repeating_letter?(word) && all_allowed?(word), do: :nice, else: :naughty
end
defp has_three_vowels?(word) do
Enum.reduce([?a, ?e, ?i, ?o, ?u], 0, fn (vowel, count) ->
count + length(Enum.filter(word, fn letter -> letter == vowel end))
end) >= 3
end
defp has_repeating_letter?(word) do
length(Enum.dedup(word)) < length(word)
end
defp all_allowed?(word) do
word_as_string = to_string(word)
Enum.reduce(["ab", "cd", "pq", "xy"], true, fn (not_allowed, previous_check) ->
previous_check && !String.contains?(word_as_string, not_allowed)
end)
end
end
{:ok, input} = File.read("input/day5.txt")
parsed_words = input
|> String.split("\n")
|> Enum.map(&to_char_list/1)
IO.inspect Day5.how_many_nice(parsed_words)
IO.inspect Day5.how_many_nice_part_2(parsed_words)