Line data Source code
1 : #include "LinewiseInput.h"
2 : #include "PuzzleImpl.h"
3 :
4 : #include <libassert/assert.hpp>
5 : #include <re2/re2.h>
6 :
7 : #include <algorithm>
8 : #include <cstdint>
9 : #include <numeric>
10 :
11 : namespace {
12 :
13 : struct Present {
14 2000 : Present(std::string_view const s) {
15 2000 : static RE2 const boxPattern(R"((\d+)x(\d+)x(\d+))");
16 2000 : ASSUME(RE2::FullMatch(s, boxPattern, &l, &w, &h));
17 2000 : }
18 :
19 1000 : [[nodiscard]] uint64_t surfaceArea() const { return uint64_t(2) * (l * w + w * h + h * l); }
20 1000 : [[nodiscard]] uint64_t volume() const { return l * w * h; }
21 1000 : [[nodiscard]] uint64_t minFaceArea() const { return std::min({l * w, w * h, h * l}); }
22 1000 : [[nodiscard]] uint64_t minCircumference() const {
23 1000 : return uint64_t(2) * std::min({l + w, w + h, h + l});
24 1000 : }
25 :
26 1000 : [[nodiscard]] uint64_t requiredPaper() const { return surfaceArea() + minFaceArea(); }
27 1000 : [[nodiscard]] uint64_t requiredRibbon() const { return minCircumference() + volume(); }
28 :
29 : uint64_t l = 0u;
30 : uint64_t w = 0u;
31 : uint64_t h = 0u;
32 : };
33 :
34 : } // namespace
35 :
36 1 : template <> size_t part1<2015, 2>(std::string_view const input) {
37 1 : LinewiseInput const lines(input);
38 1 : return std::transform_reduce(lines.begin(), lines.end(), uint64_t(0), std::plus<>{},
39 1000 : [](std::string_view const s) { return Present(s).requiredPaper(); });
40 1 : }
41 :
42 1 : template <> size_t part2<2015, 2>(std::string_view const input) {
43 1 : LinewiseInput const lines(input);
44 1 : return std::transform_reduce(
45 1 : lines.begin(), lines.end(), uint64_t(0), std::plus<>{},
46 1000 : [](std::string_view const s) { return Present(s).requiredRibbon(); });
47 1 : }
|