AoC code coverage
Current view: top level - puzzles/2023 - Day07.cpp (source / functions) Coverage Total Hit
Test: master Lines: 69.7 % 119 83
Test Date: 2025-12-11 19:43:23 Functions: 85.7 % 14 12

            Line data    Source code
       1              : #include "AsciiMap.h"
       2              : #include "LinewiseInput.h"
       3              : #include "PuzzleImpl.h"
       4              : 
       5              : #include <libassert/assert.hpp>
       6              : 
       7              : #include <algorithm>
       8              : #include <charconv>
       9              : #include <cstdint>
      10              : #include <span>
      11              : #include <string>
      12              : 
      13              : namespace {
      14              : 
      15              : constexpr size_t numCards = 5u;
      16              : using Deck = std::span<char const, numCards>;
      17              : using Bid = unsigned short;
      18              : 
      19            0 : static constexpr AsciiMap<unsigned> makeCardValueMapPt1() {
      20            0 :   AsciiMap<unsigned> map('\0');
      21            0 :   map['2'] = 0u;
      22            0 :   map['3'] = 1u;
      23            0 :   map['4'] = 2u;
      24            0 :   map['5'] = 3u;
      25            0 :   map['6'] = 4u;
      26            0 :   map['7'] = 5u;
      27            0 :   map['8'] = 6u;
      28            0 :   map['9'] = 7u;
      29            0 :   map['T'] = 8u;
      30            0 :   map['J'] = 9u;
      31            0 :   map['Q'] = 10u;
      32            0 :   map['K'] = 11u;
      33            0 :   map['A'] = 12u;
      34            0 : 
      35            0 :   return map;
      36            0 : }
      37              : 
      38            0 : static constexpr AsciiMap<unsigned> makeCardValueMapPt2() {
      39            0 :   AsciiMap<unsigned> map('\0');
      40            0 :   map['J'] = 0u;
      41            0 :   map['2'] = 1u;
      42            0 :   map['3'] = 2u;
      43            0 :   map['4'] = 3u;
      44            0 :   map['5'] = 4u;
      45            0 :   map['6'] = 5u;
      46            0 :   map['7'] = 6u;
      47            0 :   map['8'] = 7u;
      48            0 :   map['9'] = 8u;
      49            0 :   map['T'] = 9u;
      50            0 :   map['Q'] = 10u;
      51            0 :   map['K'] = 11u;
      52            0 :   map['A'] = 12u;
      53            0 : 
      54            0 :   return map;
      55            0 : }
      56              : 
      57              : struct Part1 {
      58              : 
      59              :   static constexpr auto cardValueMap = makeCardValueMapPt1();
      60              : 
      61         1000 :   static unsigned getValue(Deck const &deck) {
      62         1000 :     std::array<unsigned, 13u> frequency{};
      63         5000 :     for (char card : deck) {
      64         5000 :       ++frequency[cardValueMap[card]];
      65         5000 :     }
      66              : 
      67         1000 :     std::partial_sort(frequency.begin(), std::next(frequency.begin(), 2), frequency.end(),
      68        13791 :                       [](unsigned lhs, unsigned rhs) { return lhs > rhs; });
      69              : 
      70         1000 :     unsigned const &mostFrequent = frequency[0];
      71         1000 :     unsigned const &secondMostFrequent = frequency[1];
      72              : 
      73         1000 :     unsigned value = 0;
      74         1000 :     if (mostFrequent == 5u) {
      75            1 :       value = 6;
      76          999 :     } else if (mostFrequent == 4u) {
      77           96 :       value = 5;
      78          903 :     } else if (mostFrequent + secondMostFrequent == 5u) {
      79          101 :       value = 4;
      80          802 :     } else if (mostFrequent == 3u) {
      81          175 :       value = 3;
      82          627 :     } else if (mostFrequent + secondMostFrequent == 4u) {
      83          178 :       value = 2;
      84          449 :     } else if (mostFrequent == 2u) {
      85          256 :       value = 1;
      86          256 :     }
      87              : 
      88         5000 :     for (char card : deck) {
      89         5000 :       value <<= 5u;
      90         5000 :       value += cardValueMap[card];
      91         5000 :     }
      92              : 
      93         1000 :     return value;
      94         1000 :   }
      95              : };
      96              : 
      97              : struct Part2 {
      98              : 
      99              :   static constexpr auto cardValueMap = makeCardValueMapPt2();
     100              : 
     101         1000 :   static unsigned getValue(Deck const &deck) {
     102         1000 :     std::array<unsigned, 13u> frequency{};
     103         5000 :     for (char card : deck) {
     104         5000 :       ++frequency[cardValueMap[card]];
     105         5000 :     }
     106              : 
     107         1000 :     unsigned const numJokers = frequency[cardValueMap['J']];
     108         1000 :     frequency[cardValueMap['J']] = 0;
     109              : 
     110         1000 :     std::partial_sort(frequency.begin(), std::next(frequency.begin(), 2), frequency.end(),
     111        13946 :                       [](unsigned lhs, unsigned rhs) { return lhs > rhs; });
     112              : 
     113         1000 :     unsigned const &mostFrequent = frequency[0];
     114         1000 :     unsigned const &secondMostFrequent = frequency[1];
     115              : 
     116         1000 :     unsigned value = 0;
     117         1000 :     if (mostFrequent + numJokers == 5u) {
     118           30 :       value = 6;
     119          970 :     } else if (mostFrequent + numJokers == 4u) {
     120          160 :       value = 5;
     121          810 :     } else if (mostFrequent + secondMostFrequent + numJokers == 5u) {
     122          119 :       value = 4;
     123          691 :     } else if (mostFrequent + numJokers == 3u) {
     124          235 :       value = 3;
     125          456 :     } else if (mostFrequent + secondMostFrequent + numJokers == 4u) {
     126          123 :       value = 2;
     127          333 :     } else if (mostFrequent + numJokers == 2u) {
     128          217 :       value = 1;
     129          217 :     }
     130              : 
     131         5000 :     for (char card : deck) {
     132         5000 :       value <<= 5u;
     133         5000 :       value += cardValueMap[card];
     134         5000 :     }
     135              : 
     136         1000 :     return value;
     137         1000 :   }
     138              : };
     139              : 
     140              : template <typename Part> struct Game {
     141         2000 :   Game(std::string_view const s) : value(Part::getValue(Deck{s.begin(), 5u})) {
     142         2000 :     [[maybe_unused]] std::from_chars_result result =
     143         2000 :         std::from_chars(std::next(s.begin(), 6), s.end(), bid);
     144         2000 :     DEBUG_ASSERT(result.ec == std::errc());
     145         2000 :   }
     146              :   unsigned value = 0;
     147              :   Bid bid = 0;
     148              : };
     149              : 
     150            2 : template <typename Part> size_t run(std::string_view const input) {
     151            2 :   LinewiseInput const lines(input);
     152              : 
     153            2 :   std::vector<Game<Part>> games(lines.begin(), lines.end());
     154              : 
     155            2 :   std::sort(games.begin(), games.end(),
     156        24008 :             [](auto const &lhs, auto const &rhs) { return lhs.value < rhs.value; });
     157              : 
     158            2 :   uint64_t rank = 1u;
     159            2 :   uint64_t sum = 0u;
     160         2000 :   for (auto const &game : games) {
     161         2000 :     sum += rank++ * game.bid;
     162         2000 :   }
     163              : 
     164            2 :   return sum;
     165            2 : }
     166              : 
     167              : } // namespace
     168              : 
     169            1 : template <> std::string solvePart1<2023, 7>(std::string_view const input) {
     170            1 :   return std::to_string(run<Part1>(input));
     171            1 : }
     172              : 
     173            1 : template <> std::string solvePart2<2023, 7>(std::string_view const input) {
     174            1 :   return std::to_string(run<Part2>(input));
     175            1 : }
        

Generated by: LCOV version 2.0-1