AoC code coverage
Current view: top level - puzzles/2023 - Day15.cpp (source / functions) Coverage Total Hit
Test: master Lines: 83.5 % 85 71
Test Date: 2025-12-11 19:43:23 Functions: 91.7 % 12 11

            Line data    Source code
       1              : #include "Parsing.h"
       2              : #include "PuzzleImpl.h"
       3              : 
       4              : #include <libassert/assert.hpp>
       5              : #include <re2/re2.h>
       6              : 
       7              : #include <algorithm>
       8              : #include <iostream>
       9              : #include <numeric>
      10              : #include <string>
      11              : #include <string_view>
      12              : 
      13              : namespace {
      14              : 
      15        31645 : size_t hash(size_t h, char const c) {
      16        31645 :   h += static_cast<size_t>(c);
      17        31645 :   h *= size_t(17);
      18        31645 :   h %= size_t(256);
      19              : 
      20        31645 :   return h;
      21        31645 : }
      22              : 
      23         8000 : size_t hash(std::string_view const s) {
      24         8000 :   size_t h = 0;
      25         8000 :   for (char const c : s)
      26        31645 :     h = hash(h, c);
      27         8000 :   return h;
      28         8000 : }
      29              : 
      30              : class HashMap {
      31              :   using Bucket = std::vector<std::pair<std::string_view, unsigned>>;
      32              : 
      33              : public:
      34         2007 :   void emplace(std::string_view const label, unsigned value) {
      35         2007 :     Bucket &bucket = _buckets[hash(label)];
      36              : 
      37         2289 :     auto it = std::ranges::find_if(bucket, [label](auto const &p) { return label == p.first; });
      38              : 
      39         2007 :     if (it == bucket.end())
      40         1136 :       bucket.emplace_back(label, value);
      41          871 :     else
      42          871 :       it->second = value;
      43         2007 :   }
      44              : 
      45         1993 :   void erase(std::string_view const label) {
      46         1993 :     Bucket &bucket = _buckets[hash(label)];
      47              : 
      48         2188 :     auto it = std::ranges::find_if(bucket, [label](auto const &p) { return label == p.first; });
      49              : 
      50         1993 :     if (it != bucket.end())
      51          889 :       bucket.erase(it);
      52         1993 :   }
      53              : 
      54            0 :   [[maybe_unused]] friend std::ostream &operator<<(std::ostream &oss, HashMap const &map) {
      55            0 :     for (size_t i = 0; i < map._buckets.size(); ++i) {
      56            0 :       if (map._buckets[i].empty())
      57            0 :         continue;
      58            0 :       oss << "Box " << i << ": ";
      59            0 :       for (auto const &[k, v] : map._buckets[i]) {
      60            0 :         oss << "[" << k << " " << size_t(v) << "] ";
      61            0 :       }
      62            0 :       oss << "\n";
      63            0 :     }
      64            0 :     return oss;
      65            0 :   }
      66              : 
      67            1 :   [[nodiscard]] size_t focussingPower() const {
      68            1 :     size_t r = 0;
      69            1 :     size_t i = 1;
      70          256 :     for (Bucket const &bucket : _buckets) {
      71          256 :       size_t j = 1;
      72          256 :       for (auto const &[k, v] : bucket) {
      73          247 :         r += i * j * static_cast<size_t>(v);
      74          247 :         ++j;
      75          247 :       }
      76          256 :       ++i;
      77          256 :     }
      78            1 :     return r;
      79            1 :   }
      80              : 
      81              : private:
      82              :   std::array<Bucket, 256u> _buckets;
      83              : };
      84              : 
      85         4000 : void performOperation(std::string_view const input, HashMap &map) {
      86         4000 :   static RE2 const pattern = R"(([a-z]+)([-=])(\d?))";
      87         4000 :   std::string_view label;
      88         4000 :   char op = 0;
      89         4000 :   std::optional<unsigned> value;
      90         4000 :   RE2::FullMatch(input, pattern, &label, &op, &value);
      91              : 
      92         4000 :   switch (op) {
      93         2007 :   case '=':
      94         2007 :     if (!value)
      95         2007 :       PANIC(input);
      96         2007 :     else
      97         2007 :       map.emplace(label, *value);
      98         2007 :     break;
      99         1993 :   case '-':
     100         1993 :     map.erase(label);
     101         1993 :     break;
     102            0 :   default:
     103            0 :     PANIC(input);
     104         4000 :   };
     105         4000 : }
     106              : 
     107              : } // namespace
     108              : 
     109            1 : template <> std::string solvePart1<2023, 15>(std::string_view const input) {
     110            1 :   std::vector<std::string_view> inputs = split(input, ',');
     111              : 
     112            1 :   return std::to_string(std::transform_reduce(inputs.begin(), inputs.end(), size_t(0),
     113            1 :                                               std::plus<>(),
     114         4000 :                                               [](std::string_view const s) { return hash(s); }));
     115            1 : }
     116              : 
     117            1 : template <> std::string solvePart2<2023, 15>(std::string_view const input) {
     118            1 :   std::vector<std::string_view> inputs = split(input, ',');
     119              : 
     120            1 :   HashMap map;
     121         4000 :   for (auto const &in : inputs) {
     122         4000 :     performOperation(in, map);
     123         4000 :   }
     124              : 
     125              :   // std::cout << map;
     126              : 
     127            1 :   return std::to_string(map.focussingPower());
     128            1 : }
        

Generated by: LCOV version 2.0-1