make 13 more efficient! (no more temporaries)

This commit is contained in:
Eric Mertens 2023-03-27 15:59:12 -07:00
parent 0ebaa66b24
commit d5cd72f4bc

View File

@ -9,29 +9,49 @@
#include <doctest.h> #include <doctest.h>
#include <aocpp/Startup.hpp> #include <aocpp/Startup.hpp>
#include <aocpp/Overloaded.hpp>
namespace { namespace {
struct Tree { struct Tree {
std::variant<std::int64_t, std::vector<Tree>> var; std::variant<std::int64_t, std::vector<Tree>> rep;
auto operator<(Tree const& rhs) const -> bool {
if (var.index() == 0) {
if (rhs.var.index() == 0) {
return std::get<0>(var) < std::get<0>(rhs.var);
} else {
return Tree{std::vector{*this}} < rhs;
}
} else {
if (rhs.var.index() == 0) {
return *this < Tree{std::vector{rhs}};
} else {
return std::get<1>(var) < std::get<1>(rhs.var);
}
}
}
}; };
auto operator<(Tree const& lhs, Tree const& rhs) -> bool;
auto operator<(std::vector<Tree> const& x, std::int64_t y) -> bool;
auto operator<(std::int64_t x, std::vector<Tree> const& y) -> bool;
auto operator<(Tree const& x, std::int64_t y) -> bool;
auto operator<(std::int64_t x, Tree const& y) -> bool;
auto operator<(std::int64_t x, std::vector<Tree> const& y) -> bool {
switch (y.size()) {
case 0: return false;
case 1: return x < y[0];
default: return !(y[0] < x);
}
}
auto operator<(std::vector<Tree> const& x, std::int64_t y) -> bool {
switch (x.size()) {
case 0: return true;
default: return x[0] < y;
}
}
auto operator<(Tree const& x, std::int64_t y) -> bool {
return std::visit([y](auto const& x_) { return x_ < y; }, x.rep);
}
auto operator<(std::int64_t x, Tree const& y) -> bool {
return std::visit([x](auto const& y_) { return x < y_; }, y.rep);
}
auto operator<(Tree const& lhs, Tree const& rhs) -> bool {
return std::visit(std::less(), lhs.rep, rhs.rep);
}
using Input = std::vector<Tree>; using Input = std::vector<Tree>;
auto ParseTree(std::string::iterator & begin, std::string::iterator end) -> Tree auto ParseTree(std::string::iterator & begin, std::string::iterator end) -> Tree
@ -87,12 +107,12 @@ auto Part1(Input const& input) -> std::int64_t
return result; return result;
} }
auto Part2(Input input) -> std::int64_t auto Part2(Input const& input) -> std::int64_t
{ {
Tree two {std::vector{Tree{std::vector{Tree{2}}}}}; Tree two {std::vector{Tree{std::vector{Tree{2}}}}};
Tree six {std::vector{Tree{std::vector{Tree{6}}}}}; Tree six {std::vector{Tree{std::vector{Tree{6}}}}};
auto ix2 = std::count_if(input.begin(), input.end(), [&](auto x) { return x < two; }); auto ix2 = std::count_if(input.begin(), input.end(), [&](auto const& x) { return x < two; });
auto ix6 = std::count_if(input.begin(), input.end(), [&](auto x) { return x < six; }); auto ix6 = std::count_if(input.begin(), input.end(), [&](auto const& x) { return x < six; });
return (ix2+1) * (ix6+2); return (ix2+1) * (ix6+2);
} }
@ -142,8 +162,7 @@ TEST_SUITE("2022-13 examples") {
auto Main(std::istream & in, std::ostream & out) -> void auto Main(std::istream & in, std::ostream & out) -> void
{ {
auto input = Parse(in); auto const input = Parse(in);
out << "count " << input.size() << std::endl;
out << "Part 1: " << Part1(input) << std::endl; out << "Part 1: " << Part1(input) << std::endl;
out << "Part 2: " << Part2(std::move(input)) << std::endl; out << "Part 2: " << Part2(input) << std::endl;
} }