1
1
defmodule Day5 do
2
+ # Part 2 functions
3
+ def how_many_nice_part_2 ( words ) do
4
+ Enum . reduce ( words , 0 , fn ( word , count ) ->
5
+ count + ( if naughty_or_nice_part_2 ( word ) == :nice , do: 1 , else: 0 )
6
+ end )
7
+ end
8
+
9
+ def naughty_or_nice_part_2 ( word ) do
10
+ if has_two_letters_repeating_twice? ( word ) && repeats_with_one_letter_between? ( word ) , do: :nice , else: :naughty
11
+ end
12
+
13
+ def has_two_letters_repeating_twice? ( word ) do
14
+ prepared_word = remove_exactly_three_in_a_row ( word )
15
+ all_pairs = Enum . chunk ( prepared_word , 2 ) ++ Enum . chunk ( tl ( prepared_word ) , 2 )
16
+ length ( Enum . uniq ( all_pairs ) ) < length ( all_pairs )
17
+ end
18
+
19
+ defp remove_exactly_three_in_a_row ( [ h | rest = [ h2 | [ h3 | [ h4 | _ ] ] ] ] , previous \\ '' ) do
20
+ if h == h2 && h == h3 && h != h4 && h != previous do
21
+ remove_exactly_three_in_a_row ( rest , h )
22
+ else
23
+ [ h | remove_exactly_three_in_a_row ( rest , h ) ]
24
+ end
25
+ end
26
+ 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
27
+ defp remove_exactly_three_in_a_row ( rest , previous ) , do: rest
28
+
29
+ defp repeats_with_one_letter_between? ( word ) do
30
+ if length ( word ) < 3 do
31
+ false
32
+ else
33
+ Enum . zip ( word , tl ( word ) )
34
+ |> Enum . zip ( word |> tl |> tl )
35
+ |> Enum . map ( fn { { x , y } , z } -> [ x , y , z ] end )
36
+ |> Enum . any? ( fn [ first , _ , last ] -> first == last end )
37
+ end
38
+ end
39
+
40
+ # Part 1 functions
2
41
def how_many_nice ( words ) do
3
42
Enum . reduce ( words , 0 , fn ( word , count ) ->
4
43
count + ( if naughty_or_nice ( word ) == :nice , do: 1 , else: 0 )
5
44
end )
6
45
end
7
46
8
47
defp naughty_or_nice ( word ) do
9
- if has_three_vowels ( word ) && has_repeating_letter ( word ) && all_allowed ( word ) , do: :nice , else: :naughty
48
+ if has_three_vowels? ( word ) && has_repeating_letter? ( word ) && all_allowed? ( word ) , do: :nice , else: :naughty
10
49
end
11
50
12
- defp has_three_vowels ( word ) do
51
+ defp has_three_vowels? ( word ) do
13
52
Enum . reduce ( [ ?a , ?e , ?i , ?o , ?u ] , 0 , fn ( vowel , count ) ->
14
53
count + length ( Enum . filter ( word , fn letter -> letter == vowel end ) )
15
54
end ) >= 3
16
55
end
17
56
18
- defp has_repeating_letter ( word ) do
57
+ defp has_repeating_letter? ( word ) do
19
58
length ( Enum . dedup ( word ) ) < length ( word )
20
59
end
21
60
22
- defp all_allowed ( word ) do
61
+ defp all_allowed? ( word ) do
23
62
word_as_string = to_string ( word )
24
63
Enum . reduce ( [ "ab" , "cd" , "pq" , "xy" ] , true , fn ( not_allowed , previous_check ) ->
25
64
previous_check && ! String . contains? ( word_as_string , not_allowed )
@@ -34,3 +73,4 @@ parsed_words = input
34
73
|> Enum . map ( & to_char_list / 1 )
35
74
36
75
IO . inspect Day5 . how_many_nice ( parsed_words )
76
+ IO . inspect Day5 . how_many_nice_part_2 ( parsed_words )
0 commit comments