#include #include #include #include #include #include #include using namespace std; namespace { struct Record { int guard_id; long start_sleep; long stop_sleep; }; long to_timestamp(const string& line) { long year = stol(line.substr(1, 4)); long mon = stol(line.substr(6, 2)); long day = stol(line.substr(9, 2)); long hour = stol(line.substr(12, 2)); long min = stol(line.substr(15, 2)); auto timestamp = (year * 100'000'000) + (mon * 1'000'000) + (day * 10'000) + (hour * 100) + min; // NOLINT return timestamp; } vector read_file(const filesystem::path& filename) { ifstream file{ filename }; vector lines; for ( string line; getline(file, line); ) { lines.emplace_back(line); } ranges::sort(lines); vector records; int guard = -1; long start_sleep = -1; long stop_sleep = -1; for ( const auto& line: lines ) { if ( line.find(" Guard #") != string::npos ) { guard = stoi(line.substr(26)); } else if ( line.find(" falls asleep") != string::npos ) { start_sleep = to_timestamp(line); } else if ( line.find(" wakes up") != string::npos ) { stop_sleep = to_timestamp(line); records.emplace_back(guard, start_sleep, stop_sleep); } } return records; } void part1(const vector& records) { map sleep_amounts; for ( const auto& record: records ) { sleep_amounts[record.guard_id] += record.stop_sleep - record.start_sleep; } auto max_amount = ranges::max_element(sleep_amounts, [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); map sleep_counts; for ( const auto& record: records ) { if ( record.guard_id != max_amount->first ) { continue; } for ( auto timestamp = record.start_sleep; timestamp != record.stop_sleep; ++timestamp ) { sleep_counts[timestamp % 10'000]++; } } auto max_count = ranges::max_element(sleep_counts, [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); cout << "Part 1: " << max_amount->first * (max_count->first % 100) << '\n'; } void part2(const vector& records) { map> sleep_counts; for ( const auto& record: records ) { for ( auto timestamp = record.start_sleep; timestamp != record.stop_sleep; ++timestamp ) { sleep_counts[record.guard_id][timestamp % 10'000]++; } } int found_guard = -1; long found_min = -1; unsigned max_count = 0; for ( const auto& [id, times]: sleep_counts ) { for ( const auto& [min, count]: times ) { if ( count > max_count ) { max_count = count; found_guard = id; found_min = min % 100; } } } cout << "Part 2: " << found_guard * found_min << '\n'; } } // namespace int main() { auto records = read_file("data/day04.txt"); part1(records); part2(records); }