AoC code coverage
Current view: top level - puzzles/2023 - Day16.cpp (source / functions) Coverage Total Hit
Test: master Lines: 92.1 % 114 105
Test Date: 2025-07-28 10:53:57 Functions: 100.0 % 7 7

            Line data    Source code
       1              : #include "Grid2d.h"
       2              : #include "LinewiseInput.h"
       3              : #include "PuzzleImpl.h"
       4              : 
       5              : #include <libassert/assert.hpp>
       6              : #include <re2/re2.h>
       7              : 
       8              : #include <algorithm>
       9              : #include <execution>
      10              : #include <iostream>
      11              : #include <numeric>
      12              : #include <stack>
      13              : #include <string_view>
      14              : 
      15              : namespace {
      16              : 
      17              : using GridView = Grid2dSpan<char>;
      18              : using VisitedGridView = Grid2dSpan<uint8_t>;
      19              : using Coord = GridView::Coord;
      20              : 
      21              : enum Dir : uint8_t { N = 0, E = 1, S = 2, W = 3 };
      22              : constexpr std::array<Coord, 4u> stencil = {{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}};
      23              : 
      24          441 : Grid2d<uint8_t> makeVisitedGrid(int xSize, int ySize) {
      25          441 :   Grid2d<uint8_t> visited(xSize, ySize, 0b1111, 1);
      26        48947 :   for (int y = 0; y < visited.ySize(); ++y)
      27      5370638 :     for (int x = 0; x < visited.xSize(); ++x)
      28      5322132 :       visited[x, y] = 0;
      29          441 :   return visited;
      30          441 : }
      31              : 
      32          441 : size_t walkGrid(GridView const g, Coord startPos, Dir startDir) {
      33          441 :   Grid2d<uint8_t> visited = makeVisitedGrid(g.xSize(), g.ySize());
      34          441 :   std::stack<std::pair<Coord, Dir>> startPoints;
      35          441 :   startPoints.emplace(startPos, startDir);
      36              : 
      37        74998 :   while (!startPoints.empty()) {
      38        74998 :     auto [c, d] = startPoints.top();
      39        74998 :     startPoints.pop();
      40              : 
      41      3045188 :     while ((visited[c] & 1u << d) == 0u) {
      42      2977367 :       visited[c] |= 1u << d;
      43              : 
      44      2977367 :       switch (g[c]) {
      45      2671762 :       case '.':
      46      2671762 :         break;
      47        69013 :       case '|':
      48        69013 :         switch (d) {
      49        16279 :         case N:
      50        33135 :         case S:
      51        33135 :           break;
      52        16814 :         case E:
      53        35885 :         case W:
      54        35885 :           d = N;
      55        35885 :           startPoints.emplace(c + stencil[S], S);
      56        35885 :           break;
      57            0 :         default:
      58            0 :           UNREACHABLE();
      59        69013 :         }
      60        69015 :         break;
      61        76605 :       case '-':
      62        76605 :         switch (d) {
      63        18572 :         case N:
      64        38677 :         case S:
      65        38677 :           d = E;
      66        38677 :           startPoints.emplace(c + stencil[W], W);
      67        38677 :           break;
      68        19598 :         case E:
      69        37926 :         case W:
      70        37926 :           break;
      71            0 :         default:
      72            0 :           UNREACHABLE();
      73        76605 :         }
      74        76594 :         break;
      75        85762 :       case '/':
      76        85762 :         switch (d) {
      77        21650 :         case N:
      78        21650 :           d = E;
      79        21650 :           break;
      80        20609 :         case S:
      81        20609 :           d = W;
      82        20609 :           break;
      83        22398 :         case E:
      84        22398 :           d = N;
      85        22398 :           break;
      86        21104 :         case W:
      87        21104 :           d = S;
      88        21104 :           break;
      89            0 :         default:
      90            0 :           UNREACHABLE();
      91        85762 :         }
      92        85748 :         break;
      93        85748 :       case '\\':
      94        70707 :         switch (d) {
      95        17793 :         case N:
      96        17793 :           d = W;
      97        17793 :           break;
      98        17293 :         case S:
      99        17293 :           d = E;
     100        17293 :           break;
     101        18265 :         case E:
     102        18265 :           d = S;
     103        18265 :           break;
     104        17300 :         case W:
     105        17300 :           d = N;
     106        17300 :           break;
     107            0 :         default:
     108            0 :           UNREACHABLE();
     109        70707 :         }
     110        70702 :         break;
     111        70702 :       default:
     112            0 :         UNREACHABLE();
     113      2977367 :       }
     114      2970190 :       c += stencil[d];
     115      2970190 :     }
     116        74998 :   }
     117  >1844*10^16 :   return visited.count_if([](auto const &bits) { return bits != 0; });
     118          441 : }
     119              : 
     120              : } // namespace
     121              : 
     122            1 : template <> size_t part1<2023, 16>(std::string_view const input) {
     123            1 :   LinewiseInput lines(input);
     124            1 :   Grid2d<char> grid = lines.makeCharGrid2d();
     125              : 
     126            1 :   return walkGrid(grid, {0, grid.ySize() - 1}, E);
     127            1 : }
     128              : 
     129            1 : template <> size_t part2<2023, 16>(std::string_view const input) {
     130            1 :   LinewiseInput lines(input);
     131            1 :   Grid2d<char> grid = lines.makeCharGrid2d();
     132              : 
     133            1 :   std::vector<std::pair<Coord, Dir>> startPoints;
     134            1 :   startPoints.reserve(2 * grid.xSize() + 2 * grid.ySize());
     135              : 
     136          111 :   for (int y = 0; y < grid.ySize(); ++y) {
     137          110 :     startPoints.emplace_back(Coord{0, y}, E);
     138          110 :     startPoints.emplace_back(Coord{grid.xSize() - 1, y}, W);
     139          110 :   }
     140          111 :   for (int x = 0; x < grid.xSize(); ++x) {
     141          110 :     startPoints.emplace_back(Coord{x, 0}, N);
     142          110 :     startPoints.emplace_back(Coord{x, grid.ySize() - 1}, S);
     143          110 :   }
     144              : 
     145            1 :   return std::transform_reduce(
     146            1 :       std::execution::par, startPoints.begin(), startPoints.end(), size_t(0),
     147          440 :       [](size_t lhs, size_t rhs) { return std::max(lhs, rhs); },
     148          440 :       [&grid](auto const &startPos) { return walkGrid(grid, startPos.first, startPos.second); });
     149            1 : }
        

Generated by: LCOV version 2.0-1