AoC code coverage
Current view: top level - puzzles/2024 - Day05.cpp (source / functions) Coverage Total Hit
Test: master Lines: 100.0 % 66 66
Test Date: 2025-12-11 19:43:23 Functions: 100.0 % 10 10

            Line data    Source code
       1              : #include "Grid2d.h"
       2              : #include "LinewiseInput.h"
       3              : #include "Parsing.h"
       4              : #include "PuzzleImpl.h"
       5              : 
       6              : #include <libassert/assert.hpp>
       7              : 
       8              : #include <ranges>
       9              : #include <string>
      10              : #include <vector>
      11              : 
      12              : namespace {
      13              : using Rules = Grid2d<char>;
      14              : using Update = std::vector<int>;
      15              : using Updates = std::vector<Update>;
      16              : 
      17            2 : Rules parseRules(std::string_view const input) {
      18            2 :   Grid2d<char> rules(100, 100, 0);
      19              : 
      20         2352 :   auto tuples = input | std::views::split('\n') | std::views::transform([](auto &&r) {
      21         2352 :                   return r | std::views::split('|') |
      22         4704 :                          std::views::transform([](auto &&s) { return parseInt<int>(s); }) |
      23         2352 :                          std::views::adjacent<2>;
      24         2352 :                 }) |
      25            2 :                 std::views::join;
      26              : 
      27         2352 :   for (auto [x, y] : tuples) {
      28         2352 :     rules[x, y] = 1;
      29         2352 :   }
      30              : 
      31            2 :   return rules;
      32            2 : }
      33              : 
      34            2 : Updates parseUpdates(std::string_view const input) {
      35            2 :   Updates updates;
      36              : 
      37          400 :   for (auto &&line : input | std::views::split('\n')) {
      38          400 :     updates.push_back(parseIntegerRange<int>(std::string_view{line}));
      39          400 :   }
      40              : 
      41            2 :   return updates;
      42            2 : }
      43              : 
      44            2 : std::tuple<Rules, std::vector<Update>> parse(std::string_view const input) {
      45              : 
      46            2 :   auto breaks = std::ranges::search(input, std::string_view("\n\n"));
      47              : 
      48            2 :   ASSUME(!breaks.empty());
      49              : 
      50            2 :   return std::make_tuple(parseRules({input.begin(), breaks.begin()}),
      51            2 :                          parseUpdates({breaks.end(), input.end()}));
      52            2 : }
      53              : 
      54          400 : bool isValid(Update const &update, Rules const &rules) {
      55         3754 :   for (auto it = update.begin(); it != update.end(); ++it) {
      56        29944 :     for (auto it2 = std::next(it); it2 != update.end(); ++it2) {
      57        26590 :       if (rules[*it2, *it] == 1)
      58          172 :         return false;
      59        26590 :     }
      60         3526 :   }
      61          228 :   return true;
      62          400 : }
      63              : 
      64           86 : void sort(Update &update, Rules const &rules) {
      65         1422 :   for (auto it = update.begin(); it != update.end(); ++it) {
      66        38143 :     for (auto it2 = std::next(it); it2 != update.end(); ++it2) {
      67        36807 :       if (rules[*it2, *it] == 1) {
      68         5495 :         std::iter_swap(it, it2);
      69         5495 :         it2 = it;
      70         5495 :       }
      71        36807 :     }
      72         1336 :   }
      73           86 : }
      74              : 
      75          200 : int middleElement(Update const &update) { return update[update.size() / 2]; }
      76              : 
      77              : } // namespace
      78              : 
      79            1 : template <> std::string solvePart1<2024, 5>(std::string_view const input) {
      80            1 :   auto [rules, updates] = parse(input);
      81              : 
      82            1 :   uint64_t sum = 0;
      83          200 :   for (auto const &u : updates) {
      84          200 :     if (isValid(u, rules))
      85          114 :       sum += middleElement(u);
      86          200 :   }
      87            1 :   return std::to_string(sum);
      88            1 : }
      89              : 
      90            1 : template <> std::string solvePart2<2024, 5>(std::string_view const input) {
      91            1 :   auto [rules, updates] = parse(input);
      92              : 
      93            1 :   uint64_t sum = 0;
      94          200 :   for (auto &u : updates) {
      95          200 :     if (!isValid(u, rules)) {
      96           86 :       sort(u, rules);
      97           86 :       sum += middleElement(u);
      98           86 :     }
      99          200 :   }
     100            1 :   return std::to_string(sum);
     101            1 : }
        

Generated by: LCOV version 2.0-1