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

Generated by: LCOV version 2.0-1