diff options
Diffstat (limited to '2018/src/day04.cpp')
| -rw-r--r-- | 2018/src/day04.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/2018/src/day04.cpp b/2018/src/day04.cpp new file mode 100644 index 0000000..ea3c69f --- /dev/null +++ b/2018/src/day04.cpp | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | #include <algorithm> | ||
| 2 | #include <filesystem> | ||
| 3 | #include <fstream> | ||
| 4 | #include <iostream> | ||
| 5 | #include <map> | ||
| 6 | #include <string> | ||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | using namespace std; | ||
| 10 | |||
| 11 | namespace { | ||
| 12 | |||
| 13 | struct Record { | ||
| 14 | int guard_id; | ||
| 15 | long start_sleep; | ||
| 16 | long stop_sleep; | ||
| 17 | }; | ||
| 18 | |||
| 19 | long | ||
| 20 | to_timestamp(const string& line) | ||
| 21 | { | ||
| 22 | long year = stol(line.substr(1, 4)); | ||
| 23 | long mon = stol(line.substr(6, 2)); | ||
| 24 | long day = stol(line.substr(9, 2)); | ||
| 25 | long hour = stol(line.substr(12, 2)); | ||
| 26 | long min = stol(line.substr(15, 2)); | ||
| 27 | |||
| 28 | auto timestamp = (year * 100'000'000) + (mon * 1'000'000) + (day * 10'000) + (hour * 100) + min; // NOLINT | ||
| 29 | |||
| 30 | return timestamp; | ||
| 31 | } | ||
| 32 | |||
| 33 | vector<Record> | ||
| 34 | read_file(const filesystem::path& filename) | ||
| 35 | { | ||
| 36 | ifstream file{ filename }; | ||
| 37 | vector<string> lines; | ||
| 38 | |||
| 39 | for ( string line; getline(file, line); ) { | ||
| 40 | lines.emplace_back(line); | ||
| 41 | } | ||
| 42 | |||
| 43 | ranges::sort(lines); | ||
| 44 | |||
| 45 | vector<Record> records; | ||
| 46 | |||
| 47 | int guard = -1; | ||
| 48 | long start_sleep = -1; | ||
| 49 | long stop_sleep = -1; | ||
| 50 | for ( const auto& line: lines ) { | ||
| 51 | if ( line.find(" Guard #") != string::npos ) { | ||
| 52 | guard = stoi(line.substr(26)); | ||
| 53 | } | ||
| 54 | else if ( line.find(" falls asleep") != string::npos ) { | ||
| 55 | start_sleep = to_timestamp(line); | ||
| 56 | } | ||
| 57 | else if ( line.find(" wakes up") != string::npos ) { | ||
| 58 | stop_sleep = to_timestamp(line); | ||
| 59 | records.emplace_back(guard, start_sleep, stop_sleep); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | return records; | ||
| 64 | } | ||
| 65 | |||
| 66 | void | ||
| 67 | part1(const vector<Record>& records) | ||
| 68 | { | ||
| 69 | map<int, long> sleep_amounts; | ||
| 70 | |||
| 71 | for ( const auto& record: records ) { | ||
| 72 | sleep_amounts[record.guard_id] += record.stop_sleep - record.start_sleep; | ||
| 73 | } | ||
| 74 | |||
| 75 | auto max_amount = ranges::max_element(sleep_amounts, | ||
| 76 | [](const auto& lhs, const auto& rhs) { | ||
| 77 | return lhs.second < rhs.second; | ||
| 78 | }); | ||
| 79 | |||
| 80 | map<long, unsigned> sleep_counts; | ||
| 81 | |||
| 82 | for ( const auto& record: records ) { | ||
| 83 | if ( record.guard_id != max_amount->first ) { | ||
| 84 | continue; | ||
| 85 | } | ||
| 86 | |||
| 87 | for ( auto timestamp = record.start_sleep; timestamp != record.stop_sleep; ++timestamp ) { | ||
| 88 | sleep_counts[timestamp % 10'000]++; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | auto max_count = ranges::max_element(sleep_counts, | ||
| 93 | [](const auto& lhs, const auto& rhs) { | ||
| 94 | return lhs.second < rhs.second; | ||
| 95 | }); | ||
| 96 | |||
| 97 | cout << "Part 1: " << max_amount->first * (max_count->first % 100) << '\n'; | ||
| 98 | } | ||
| 99 | |||
| 100 | void | ||
| 101 | part2(const vector<Record>& records) | ||
| 102 | { | ||
| 103 | map<int, map<long, unsigned>> sleep_counts; | ||
| 104 | |||
| 105 | for ( const auto& record: records ) { | ||
| 106 | for ( auto timestamp = record.start_sleep; timestamp != record.stop_sleep; ++timestamp ) { | ||
| 107 | sleep_counts[record.guard_id][timestamp % 10'000]++; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | int found_guard = -1; | ||
| 112 | long found_min = -1; | ||
| 113 | unsigned max_count = 0; | ||
| 114 | for ( const auto& [id, times]: sleep_counts ) { | ||
| 115 | for ( const auto& [min, count]: times ) { | ||
| 116 | if ( count > max_count ) { | ||
| 117 | max_count = count; | ||
| 118 | found_guard = id; | ||
| 119 | found_min = min % 100; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | cout << "Part 2: " << found_guard * found_min << '\n'; | ||
| 125 | } | ||
| 126 | |||
| 127 | } // namespace | ||
| 128 | |||
| 129 | int | ||
| 130 | main() | ||
| 131 | { | ||
| 132 | auto records = read_file("data/day04.txt"); | ||
| 133 | part1(records); | ||
| 134 | part2(records); | ||
| 135 | } | ||
