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

Generated by: LCOV version 2.0-1