AoC code coverage
Current view: top level - puzzles/2024 - Day07.cpp (source / functions) Coverage Total Hit
Test: master Lines: 100.0 % 54 54
Test Date: 2025-07-28 10:53:57 Functions: 100.0 % 6 6

            Line data    Source code
       1              : #include "LinewiseInput.h"
       2              : #include "Parsing.h"
       3              : #include "PuzzleImpl.h"
       4              : 
       5              : #include <libassert/assert.hpp>
       6              : 
       7              : #include <algorithm>
       8              : 
       9              : namespace {
      10              : 
      11              : struct Calibration {
      12              :   uint64_t result;
      13              :   std::vector<uint64_t> operands;
      14              : };
      15              : 
      16            2 : auto parse(std::string_view const input) {
      17            2 :   std::vector<Calibration> result;
      18         1700 :   for (auto l : getLineWise(input)) {
      19         1700 :     auto it = std::ranges::find(l, ':');
      20         1700 :     ASSERT(it != l.end());
      21         1700 :     std::string_view resultStr(l.begin(), it);
      22         1700 :     std::string_view numberStr(std::next(it, 2), l.end());
      23              : 
      24         1700 :     result.push_back({parseInt<uint64_t>(resultStr), parseIntegerRange<uint64_t>(numberStr, ' ')});
      25         1700 :   }
      26              : 
      27            2 :   return result;
      28            2 : }
      29              : 
      30      2735950 : uint64_t concat(uint64_t const lhs, uint64_t const rhs) {
      31      2735950 :   uint64_t n = 1;
      32      6469265 :   while (n <= rhs)
      33      3733315 :     n *= 10u;
      34      2735950 :   return lhs * n + rhs;
      35      2735950 : }
      36              : 
      37              : bool isValidPt1(uint64_t const expectedResult, uint64_t const intermediateResult,
      38       327501 :                 std::span<uint64_t const> const operands) {
      39              : 
      40       327501 :   if (intermediateResult > expectedResult)
      41        21114 :     return false;
      42       306387 :   if (operands.empty())
      43       142670 :     return intermediateResult == expectedResult;
      44              : 
      45       163717 :   std::span<uint64_t const> const tail{std::next(operands.begin()), operands.end()};
      46       163717 :   return isValidPt1(expectedResult, intermediateResult * operands.front(), tail) ||
      47       163717 :          isValidPt1(expectedResult, intermediateResult + operands.front(), tail);
      48       306387 : }
      49              : 
      50              : bool isValidPt2(uint64_t const expectedResult, uint64_t const intermediateResult,
      51      8212091 :                 std::span<uint64_t const> const operands) {
      52              : 
      53      8212091 :   if (intermediateResult > expectedResult)
      54      1551279 :     return false;
      55      6660812 :   if (operands.empty())
      56      3922619 :     return intermediateResult == expectedResult;
      57              : 
      58      2738193 :   std::span<uint64_t const> const tail{std::next(operands.begin()), operands.end()};
      59      2738193 :   return isValidPt2(expectedResult, intermediateResult * operands.front(), tail) ||
      60      2738193 :          isValidPt2(expectedResult, intermediateResult + operands.front(), tail) ||
      61      2738193 :          isValidPt2(expectedResult, concat(intermediateResult, operands.front()), tail);
      62      6660812 : }
      63              : 
      64              : } // namespace
      65              : 
      66            1 : template <> size_t part1<2024, 7>(std::string_view const input) {
      67            1 :   std::vector<Calibration> calibrations = parse(input);
      68              : 
      69            1 :   uint64_t result = 0;
      70          850 :   for (auto &c : calibrations) {
      71          850 :     if (isValidPt1(c.result, c.operands.front(), {std::next(c.operands.begin()), c.operands.end()}))
      72          252 :       result += c.result;
      73          850 :   }
      74            1 :   return result;
      75            1 : }
      76              : 
      77            1 : template <> size_t part2<2024, 7>(std::string_view const input) {
      78            1 :   std::vector<Calibration> calibrations = parse(input);
      79              : 
      80            1 :   uint64_t result = 0;
      81          850 :   for (auto &c : calibrations) {
      82          850 :     if (isValidPt2(c.result, c.operands.front(), {std::next(c.operands.begin()), c.operands.end()}))
      83          432 :       result += c.result;
      84          850 :   }
      85            1 :   return result;
      86            1 : }
        

Generated by: LCOV version 2.0-1