aboutsummaryrefslogtreecommitdiff
path: root/2018/src/day04.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2018/src/day04.cpp')
-rw-r--r--2018/src/day04.cpp135
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
9using namespace std;
10
11namespace {
12
13struct Record {
14 int guard_id;
15 long start_sleep;
16 long stop_sleep;
17};
18
19long
20to_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
33vector<Record>
34read_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
66void
67part1(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
100void
101part2(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
129int
130main()
131{
132 auto records = read_file("data/day04.txt");
133 part1(records);
134 part2(records);
135}