AoC code coverage
Current view: top level - puzzles/2023 - Day18.cpp (source / functions) Coverage Total Hit
Test: master Lines: 96.2 % 79 76
Test Date: 2025-12-11 19:43:23 Functions: 100.0 % 7 7

            Line data    Source code
       1              : #include "Grid2d.h"
       2              : #include "LinewiseInput.h"
       3              : #include "Parsing.h"
       4              : #include "PuzzleImpl.h"
       5              : 
       6              : #include <absl/container/flat_hash_set.h>
       7              : #include <libassert/assert.hpp>
       8              : #include <re2/re2.h>
       9              : 
      10              : #include <cstdint>
      11              : #include <iostream>
      12              : #include <limits>
      13              : #include <string>
      14              : #include <string_view>
      15              : 
      16              : namespace {
      17              : 
      18              : using Coord = Vec2<int64_t>;
      19              : 
      20              : enum Dir : uint8_t { R = 0, D = 1, L = 2, U = 3 };
      21              : 
      22         1248 : Coord stencil(Dir dir) {
      23         1248 :   switch (dir) {
      24          303 :   case R:
      25          303 :     return {1, 0};
      26          318 :   case D:
      27          318 :     return {0, -1};
      28          321 :   case L:
      29          321 :     return {-1, 0};
      30          306 :   case U:
      31          306 :     return {0, 1};
      32            0 :   default:
      33            0 :     UNREACHABLE();
      34         1248 :   };
      35            0 : }
      36              : 
      37            1 : std::vector<std::pair<Dir, int>> parsePt1(std::string_view const input) {
      38            1 :   LinewiseInput lines(input);
      39              : 
      40            1 :   std::vector<std::pair<Dir, int>> result;
      41            1 :   result.reserve(lines.size());
      42              : 
      43            1 :   std::array<Dir, 128u> dirMap{};
      44            1 :   dirMap['R'] = R;
      45            1 :   dirMap['D'] = D;
      46            1 :   dirMap['L'] = L;
      47            1 :   dirMap['U'] = U;
      48              : 
      49            1 :   static RE2 const pattern = R"(([RLUD]) (\d+) \(#[a-z0-9]{6}\))";
      50              : 
      51          624 :   for (std::string_view line : lines) {
      52          624 :     char d = 0;
      53          624 :     int length = 0;
      54          624 :     ASSUME(RE2::FullMatch(line, pattern, &d, &length));
      55          624 :     result.emplace_back(dirMap[d], length);
      56          624 :   }
      57              : 
      58            1 :   return result;
      59            1 : }
      60              : 
      61            1 : std::vector<std::pair<Dir, int>> parsePt2(std::string_view const input) {
      62            1 :   LinewiseInput lines(input);
      63              : 
      64            1 :   std::vector<std::pair<Dir, int>> result;
      65            1 :   result.reserve(lines.size());
      66              : 
      67            1 :   static RE2 const pattern = R"([RLUD] \d+ \(#([a-z0-9]{5})([0-3])\))";
      68              : 
      69          624 :   for (std::string_view line : lines) {
      70          624 :     std::string_view lengthHexStr;
      71          624 :     int d = 0;
      72          624 :     ASSUME(RE2::FullMatch(line, pattern, &lengthHexStr, &d));
      73          624 :     result.emplace_back(Dir(d), parseHexInt<int>(lengthHexStr));
      74          624 :   }
      75              : 
      76            1 :   return result;
      77            1 : }
      78              : 
      79              : struct Horiziontal {
      80              :   int line;
      81              :   int offset;
      82              :   int length;
      83              : };
      84              : 
      85            2 : std::vector<Coord> getVertices(std::vector<std::pair<Dir, int>> const &digInstructions) {
      86              : 
      87            2 :   Coord pos{0, 0};
      88              : 
      89            2 :   std::vector<Coord> result;
      90            2 :   result.reserve(digInstructions.size());
      91              : 
      92            2 :   result.push_back(pos);
      93         1248 :   for (auto const &instruction : digInstructions) {
      94         1248 :     pos += instruction.second * stencil(instruction.first);
      95         1248 :     result.push_back(pos);
      96         1248 :   }
      97              : 
      98            2 :   return result;
      99            2 : }
     100              : 
     101            2 : size_t gaussianArea(std::vector<Coord> const &coords) {
     102            2 :   int64_t area = 0;
     103         1250 :   for (size_t i = 0; i < coords.size() - 1u; ++i) {
     104         1248 :     area += (coords[i].y() + coords[i + 1].y()) * (coords[i].x() - coords[i + 1].x());
     105         1248 :   }
     106            2 :   area = std::abs(area / 2);
     107              : 
     108            2 :   int64_t perimeter = 0;
     109         1250 :   for (size_t i = 0; i < coords.size() - 1u; ++i) {
     110         1248 :     perimeter +=
     111         1248 :         std::abs(coords[i].y() - coords[i + 1].y()) + std::abs(coords[i].x() - coords[i + 1].x());
     112         1248 :   }
     113              : 
     114            2 :   return integerCast<size_t>(area + perimeter / 2 + 1);
     115            2 : }
     116              : 
     117              : } // namespace
     118              : 
     119            1 : template <> std::string solvePart1<2023, 18>(std::string_view const input) {
     120            1 :   auto digInstructions = parsePt1(input);
     121            1 :   auto vertices = getVertices(digInstructions);
     122            1 :   return std::to_string(gaussianArea(vertices));
     123            1 : }
     124              : 
     125            1 : template <> std::string solvePart2<2023, 18>(std::string_view const input) {
     126            1 :   auto digInstructions = parsePt2(input);
     127            1 :   auto vertices = getVertices(digInstructions);
     128            1 :   return std::to_string(gaussianArea(vertices));
     129            1 : }
        

Generated by: LCOV version 2.0-1