+1
2015/05/part1-tests/expected
+1
2015/05/part1-tests/expected
···
1
+
2
+5
2015/05/part1-tests/input1
+5
2015/05/part1-tests/input1
+1
2015/05/part2-tests/expected
+1
2015/05/part2-tests/expected
···
1
+
2
+4
2015/05/part2-tests/input1
+4
2015/05/part2-tests/input1
+113
2015/05/solution.erl
+113
2015/05/solution.erl
···
1
+
#!/usr/bin/env escript
2
+
3
+
% --- Part 1 Code
4
+
part1(Input) ->
5
+
io:format("Part 1: ~b~n", [count_nice_strings(Input, 0)]).
6
+
7
+
count_vowels(String) ->
8
+
lists:foldl(
9
+
fun(Char, Total) ->
10
+
case lists:member(Char, "aeiou") of
11
+
true -> Total + 1;
12
+
false -> Total
13
+
end
14
+
end,
15
+
0,
16
+
String
17
+
).
18
+
19
+
has_consecutive_characters([_ | []]) ->
20
+
false;
21
+
has_consecutive_characters(String) ->
22
+
[First, Second | Rest] = String,
23
+
case First == Second of
24
+
true -> true;
25
+
false -> has_consecutive_characters([Second] ++ Rest)
26
+
end.
27
+
28
+
has_forbidden_pattern(String, Pattern) ->
29
+
case string:find(String, Pattern) of
30
+
nomatch -> false;
31
+
_ -> true
32
+
end.
33
+
34
+
is_nice_string(String) ->
35
+
maybe
36
+
true ?= count_vowels(String) >= 3,
37
+
true ?= has_consecutive_characters(String),
38
+
true ?= has_forbidden_pattern(String, "ab") == false,
39
+
true ?= has_forbidden_pattern(String, "cd") == false,
40
+
true ?= has_forbidden_pattern(String, "pq") == false,
41
+
true ?= has_forbidden_pattern(String, "xy") == false
42
+
end.
43
+
44
+
count_nice_strings([], Total) ->
45
+
Total;
46
+
count_nice_strings([Head | Rest], Total) ->
47
+
case is_nice_string(Head) of
48
+
true -> count_nice_strings(Rest, Total + 1);
49
+
false -> count_nice_strings(Rest, Total)
50
+
end.
51
+
52
+
% --- Part 2 Code
53
+
part2(Input) ->
54
+
io:format("Part 2: ~b~n", [count_nice_strings2(Input, 0)]).
55
+
56
+
has_pattern(String, Pattern) ->
57
+
case string:find(String, Pattern) of
58
+
nomatch -> false;
59
+
_ -> true
60
+
end.
61
+
62
+
has_duplicate_pattern([_ | []]) ->
63
+
false;
64
+
has_duplicate_pattern(String) ->
65
+
[First, Second | Rest] = String,
66
+
case has_pattern(Rest, [First, Second]) of
67
+
true -> true;
68
+
false -> has_duplicate_pattern([Second] ++ Rest)
69
+
end.
70
+
71
+
has_repeating_with_interrupt([_, _ | []]) ->
72
+
false;
73
+
has_repeating_with_interrupt(String) ->
74
+
[Start, Middle, End | Rest] = String,
75
+
case Start == End of
76
+
true -> true;
77
+
false -> has_repeating_with_interrupt([Middle, End] ++ Rest)
78
+
end.
79
+
80
+
is_nice_string2(String) ->
81
+
maybe
82
+
true ?= has_duplicate_pattern(String),
83
+
true ?= has_repeating_with_interrupt(String)
84
+
end.
85
+
86
+
count_nice_strings2([], Total) ->
87
+
Total;
88
+
count_nice_strings2([Head | Rest], Total) ->
89
+
case is_nice_string2(Head) of
90
+
true -> count_nice_strings2(Rest, Total + 1);
91
+
false -> count_nice_strings2(Rest, Total)
92
+
end.
93
+
94
+
% --- Generic Helper Functions
95
+
read_input() -> read_input("").
96
+
read_input(PrevLine) ->
97
+
case io:fread("", "~s") of
98
+
eof -> PrevLine;
99
+
{error, _} -> halt(1);
100
+
{ok, Terms} -> read_input(PrevLine ++ Terms)
101
+
end.
102
+
103
+
main(Args) ->
104
+
Input = read_input(),
105
+
case Args of
106
+
["1"] ->
107
+
part1(Input);
108
+
["2"] ->
109
+
part2(Input);
110
+
_ ->
111
+
part1(Input),
112
+
part2(Input)
113
+
end.