Line data Source code
1 : #include "LinewiseInput.h"
2 : #include "PuzzleImpl.h"
3 :
4 : #include <libassert/assert.hpp>
5 :
6 : #include <algorithm>
7 : #include <array>
8 : #include <iterator>
9 : #include <string_view>
10 : #include <unordered_set>
11 :
12 : namespace {
13 :
14 : using namespace std::string_view_literals;
15 :
16 1000 : bool hasThreeVowels(std::string_view const word) {
17 1000 : static std::string_view constexpr vowels{"aeiou"};
18 16000 : return std::ranges::count_if(word, [&](char const c) { return vowels.contains(c); }) >= 3u;
19 1000 : }
20 :
21 631 : bool containsDoubleLetter(std::string_view const word) {
22 631 : return std::ranges::adjacent_find(word) != word.end();
23 631 : }
24 :
25 260 : bool noBadSubstrings(std::string_view const word) {
26 260 : static std::array constexpr badSubstrings = {"ab"sv, "cd"sv, "pq"sv, "xy"sv};
27 999 : return std::ranges::none_of(badSubstrings, [&](std::string_view const badSubstring) {
28 999 : return word.contains(badSubstring);
29 999 : });
30 260 : }
31 :
32 1000 : bool hasDoubleLetterPair(std::string_view const word) {
33 14586 : for (auto it = word.begin(); it != std::prev(word.end(), 1); ++it) {
34 13715 : std::string_view const pair(it, 2u);
35 13715 : std::string_view const remainder(std::next(it, 2), word.end());
36 13715 : if (remainder.contains(pair))
37 129 : return true;
38 13715 : }
39 871 : return false;
40 1000 : }
41 :
42 129 : bool hasMirrorRepeat(std::string_view const word) {
43 1431 : for (auto it = word.begin(); it != std::prev(word.end(), 2); ++it) {
44 1371 : std::string_view const letters(it, 3u);
45 1371 : if (letters.front() == letters.back())
46 69 : return true;
47 1371 : }
48 60 : return false;
49 129 : }
50 :
51 : } // namespace
52 :
53 1 : template <> size_t part1<2015, 5>(std::string_view const input) {
54 1 : LinewiseInput lines(input);
55 1000 : return std::ranges::count_if(lines, [](std::string_view const line) {
56 1000 : return hasThreeVowels(line) && containsDoubleLetter(line) && noBadSubstrings(line);
57 1000 : });
58 1 : }
59 :
60 1 : template <> size_t part2<2015, 5>(std::string_view const input) {
61 1 : LinewiseInput lines(input);
62 1000 : return std::ranges::count_if(lines, [](std::string_view const line) {
63 1000 : return hasDoubleLetterPair(line) && hasMirrorRepeat(line);
64 1000 : });
65 1 : }
|