diff --git a/2018/puzzle-04-01.cc b/2018/puzzle-04-01.cc new file mode 100644 index 0000000..2668b03 --- /dev/null +++ b/2018/puzzle-04-01.cc @@ -0,0 +1,148 @@ +// +// Created by Matthew Gretton-Dann on 01/12/2022. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using UInt = std::uint64_t; + +using namespace std::string_literals; + +struct Event +{ + explicit Event(std::string const& s) + { + UInt pos{1}; + std::size_t l{0}; + std::stoull(s.substr(pos)); + timestamp_ = std::stoull(s.substr(pos), &l); // year + pos += l + 1; + timestamp_ *= 12; + timestamp_ += std::stoull(s.substr(pos), &l) - 1; // month + pos += l + 1; + timestamp_ *= 31; // Just need order not actual values. + timestamp_ += std::stoull(s.substr(pos), &l) - 1; // day + pos += l + 1; + timestamp_ *= 24; + timestamp_ += std::stoull(s.substr(pos), &l); // hour + pos += l + 1; + timestamp_ *= 60; + timestamp_ += std::stoull(s.substr(pos), &l); // minute + pos += l + 2; + if (s.substr(pos) == "falls asleep"s) { + wake_up_ = false; + guard_ = 0; + } + else if (s.substr(pos) == "wakes up"s) { + wake_up_ = true; + guard_ = 0; + } + else { + wake_up_ = true; + guard_ = std::stoull(s.substr(pos + 7)); + assert(guard_ != 0); + } + } + + [[nodiscard]] auto wakes_up() const noexcept -> bool { return wake_up_; } + [[nodiscard]] auto guard_id() const noexcept -> UInt { return guard_; } + [[nodiscard]] auto timestamp() const noexcept -> UInt { return timestamp_; } + + [[nodiscard]] auto operator<(Event const& r) const noexcept -> bool + { + if (timestamp_ < r.timestamp_) { + return true; + } + if (timestamp_ > r.timestamp_) { + return false; + } + if (r.wake_up_) { + return false; + } + return wake_up_; + } + +private: + UInt timestamp_{0}; + UInt guard_{0}; + bool wake_up_{false}; +}; + +auto print_timestamp(UInt timestamp) +{ + std::cout << "[" << timestamp << ": " << timestamp / static_cast(24 * 60 * 31 * 12) << "-" + << std::setw(2) << std::setfill('0') + << 1 + timestamp / static_cast(24 * 60 * 31) % 12 << "-" << std::setw(2) + << std::setfill('0') << 1 + (timestamp / static_cast(24 * 60)) % 31 << " " + << std::setw(2) << std::setfill('0') << (timestamp / 60) % 24 << ":" << std::setw(2) + << std::setfill('0') << timestamp % 60 << "]"; +} + +auto how_sleepy(std::vector const& guard) -> UInt +{ + return std::accumulate(guard.begin(), guard.end(), UInt{0}, [](UInt a, UInt b) { return a + b; }); +} + +auto main() -> int +{ + std::string line; + std::vector events; + + while (std::getline(std::cin, line)) { + events.emplace_back(line); + } + std::sort(events.begin(), events.end()); + std::map> guard_sleep_map; + auto current_it{guard_sleep_map.begin()}; + UInt asleep_from{0}; + + for (auto const& e : events) { + if (e.wakes_up()) { + if (e.guard_id() != 0) { + auto result = guard_sleep_map.insert({e.guard_id(), std::vector(60, 0)}); + current_it = result.first; + assert(asleep_from == 0); + print_timestamp(e.timestamp()); + std::cout << ": Guard " << current_it->first << " starts duty.\n"; + } + else { + assert(asleep_from != 0); + for (UInt i = asleep_from; i != e.timestamp(); ++i) { + ++(current_it->second[i % 60]); + } + print_timestamp(e.timestamp()); + std::cout << ": Guard " << current_it->first << " wakes up after " + << e.timestamp() - asleep_from << " minutes sleep. Has slept a total of " + << how_sleepy(current_it->second) << " minutes.\n"; + asleep_from = 0; + } + } + else { + assert(asleep_from == 0); + asleep_from = e.timestamp(); + print_timestamp(e.timestamp()); + std::cout << ": Guard " << current_it->first << " goes to sleep.\n"; + } + } + + auto sleepiest_guard{std::max_element(guard_sleep_map.begin(), guard_sleep_map.end(), + [](auto const& lhs, auto const& rhs) { + return how_sleepy(lhs.second) < how_sleepy(rhs.second); + })}; + auto sleepiest_guard_id{sleepiest_guard->first}; + auto sleepiest_minute{ + std::max_element(sleepiest_guard->second.begin(), sleepiest_guard->second.end()) - + sleepiest_guard->second.begin()}; + std::cout << "Busiest guard: " << sleepiest_guard_id << " was asleep most in minute " + << sleepiest_minute << "\n"; + std::cout << "Result: " << sleepiest_guard_id * sleepiest_minute << "\n"; + return EXIT_SUCCESS; +} diff --git a/2018/puzzle-04-02.cc b/2018/puzzle-04-02.cc new file mode 100644 index 0000000..419e159 --- /dev/null +++ b/2018/puzzle-04-02.cc @@ -0,0 +1,153 @@ +// +// Created by Matthew Gretton-Dann on 01/12/2022. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using UInt = std::uint64_t; + +using namespace std::string_literals; + +struct Event +{ + explicit Event(std::string const& s) + { + UInt pos{1}; + std::size_t l{0}; + std::stoull(s.substr(pos)); + timestamp_ = std::stoull(s.substr(pos), &l); // year + pos += l + 1; + timestamp_ *= 12; + timestamp_ += std::stoull(s.substr(pos), &l) - 1; // month + pos += l + 1; + timestamp_ *= 31; // Just need order not actual values. + timestamp_ += std::stoull(s.substr(pos), &l) - 1; // day + pos += l + 1; + timestamp_ *= 24; + timestamp_ += std::stoull(s.substr(pos), &l); // hour + pos += l + 1; + timestamp_ *= 60; + timestamp_ += std::stoull(s.substr(pos), &l); // minute + pos += l + 2; + if (s.substr(pos) == "falls asleep"s) { + wake_up_ = false; + guard_ = 0; + } + else if (s.substr(pos) == "wakes up"s) { + wake_up_ = true; + guard_ = 0; + } + else { + wake_up_ = true; + guard_ = std::stoull(s.substr(pos + 7)); + assert(guard_ != 0); + } + } + + [[nodiscard]] auto wakes_up() const noexcept -> bool { return wake_up_; } + [[nodiscard]] auto guard_id() const noexcept -> UInt { return guard_; } + [[nodiscard]] auto timestamp() const noexcept -> UInt { return timestamp_; } + + [[nodiscard]] auto operator<(Event const& r) const noexcept -> bool + { + if (timestamp_ < r.timestamp_) { + return true; + } + if (timestamp_ > r.timestamp_) { + return false; + } + if (r.wake_up_) { + return false; + } + return wake_up_; + } + +private: + UInt timestamp_{0}; + UInt guard_{0}; + bool wake_up_{false}; +}; + +auto print_timestamp(UInt timestamp) +{ + std::cout << "[" << timestamp << ": " << timestamp / static_cast(24 * 60 * 31 * 12) << "-" + << std::setw(2) << std::setfill('0') + << 1 + timestamp / static_cast(24 * 60 * 31) % 12 << "-" << std::setw(2) + << std::setfill('0') << 1 + (timestamp / static_cast(24 * 60)) % 31 << " " + << std::setw(2) << std::setfill('0') << (timestamp / 60) % 24 << ":" << std::setw(2) + << std::setfill('0') << timestamp % 60 << "]"; +} + +auto how_sleepy(std::vector const& guard) -> UInt +{ + return std::accumulate(guard.begin(), guard.end(), UInt{0}, [](UInt a, UInt b) { return a + b; }); +} + +auto main() -> int +{ + std::string line; + std::vector events; + + while (std::getline(std::cin, line)) { + events.emplace_back(line); + } + std::sort(events.begin(), events.end()); + std::map> guard_sleep_map; + auto current_it{guard_sleep_map.begin()}; + UInt asleep_from{0}; + + for (auto const& e : events) { + if (e.wakes_up()) { + if (e.guard_id() != 0) { + auto result = guard_sleep_map.insert({e.guard_id(), std::vector(60, 0)}); + current_it = result.first; + assert(asleep_from == 0); + print_timestamp(e.timestamp()); + std::cout << ": Guard " << current_it->first << " starts duty.\n"; + } + else { + assert(asleep_from != 0); + for (UInt i = asleep_from; i != e.timestamp(); ++i) { + ++(current_it->second[i % 60]); + } + print_timestamp(e.timestamp()); + std::cout << ": Guard " << current_it->first << " wakes up after " + << e.timestamp() - asleep_from << " minutes sleep. Has slept a total of " + << how_sleepy(current_it->second) << " minutes.\n"; + asleep_from = 0; + } + } + else { + assert(asleep_from == 0); + asleep_from = e.timestamp(); + print_timestamp(e.timestamp()); + std::cout << ": Guard " << current_it->first << " goes to sleep.\n"; + } + } + + UInt max_minute{0}; + UInt max_score{0}; + for (auto const& guard_sleep : guard_sleep_map) { + auto sleepiest_minute{std::max_element(guard_sleep.second.begin(), guard_sleep.second.end())}; + UInt const score{guard_sleep.first * (sleepiest_minute - guard_sleep.second.begin())}; + if (*sleepiest_minute > max_minute) { + max_score = score; + max_minute = *sleepiest_minute; + } + + std::cout << "Guard " << guard_sleep.first << " slept most for " << *sleepiest_minute + << " minutes at " << sleepiest_minute - guard_sleep.second.begin() + << " score: " << score << "\n"; + } + + std::cout << "Result: " << max_score << "\n"; + return EXIT_SUCCESS; +}