2024-07
This commit is contained in:
parent
d6fc0396cb
commit
b18f6ae092
63
2024/07.cpp
Normal file
63
2024/07.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include <aocpp/Parsing.hpp>
|
||||
#include <aocpp/Startup.hpp>
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <stack>
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
namespace {
|
||||
|
||||
auto
|
||||
suffixed(std::uint64_t x, std::uint64_t y) -> std::optional<std::uint64_t>
|
||||
{
|
||||
while (x > 0) {
|
||||
if (y == 0) { return x; }
|
||||
if (x % 10 != y % 10) { return {}; }
|
||||
x /= 10;
|
||||
y /= 10;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
auto
|
||||
check(bool part2, std::uint64_t target, std::vector<std::uint64_t> const& numbers) -> bool
|
||||
{
|
||||
std::stack<boost::tuple<std::size_t, std::uint64_t>> work;
|
||||
work.push({numbers.size() - 1, target});
|
||||
|
||||
while (!work.empty()){
|
||||
auto [i, t] = work.top();
|
||||
work.pop();
|
||||
auto x = numbers[i];
|
||||
if (i == 0) {
|
||||
if (x == t) return true;
|
||||
} else {
|
||||
if (x < t) { work.push({i-1, t-x}); }
|
||||
if (t % x == 0) { work.push({i-1, t/x}); }
|
||||
if (part2) { if (auto u = suffixed(t,x)) { work.push({i-1, *u}); } }
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto Main(std::istream & in, std::ostream & out) -> void
|
||||
{
|
||||
std::vector<boost::tuple<std::uint64_t, std::vector<std::uint64_t>>> input;
|
||||
aocpp::ParseSimple(in, *(qi::ulong_long >> ":" >> *(" " >> qi::ulong_long) >> "\n"), input);
|
||||
|
||||
std::uint64_t p1{}, p2{};
|
||||
for (auto && [x, xs] : input) {
|
||||
if (check(false, x, xs)) p1 += x;
|
||||
if (check(true, x, xs)) p2 += x;
|
||||
}
|
||||
|
||||
out << "Part 1: " << p1 << "\n"
|
||||
<< "Part 2: " << p2 << "\n";
|
||||
}
|
83
2024/22.cpp
Normal file
83
2024/22.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <functional>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
using Input = std::vector<std::uint32_t>;
|
||||
|
||||
auto Parse(std::istream & in) -> Input
|
||||
{
|
||||
Input results {};
|
||||
std::for_each(
|
||||
std::istream_iterator<std::string>{in},
|
||||
std::istream_iterator<std::string>{},
|
||||
[&](std::string line) {
|
||||
results.push_back(std::stoul(line));
|
||||
}
|
||||
);
|
||||
return results;
|
||||
}
|
||||
|
||||
auto Next(std::uint32_t x) -> std::uint32_t
|
||||
{
|
||||
x = (x ^ (x << 6)) & 0xffffff;
|
||||
x = (x ^ (x >> 5)) & 0xffffff;
|
||||
x = (x ^ (x << 11)) & 0xffffff;
|
||||
return x;
|
||||
}
|
||||
|
||||
auto Solve(Input entries) -> std::pair<std::uint64_t, std::uint64_t>
|
||||
{
|
||||
std::vector<std::uint32_t> patterns(std::size(entries));
|
||||
std::vector<std::uint64_t> counts(19*19*19*19);
|
||||
std::vector<bool> seen(std::size(entries)*19*19*19*19);
|
||||
|
||||
for (std::size_t i = 0; i < 3; ++i) {
|
||||
for (std::size_t j = 0; j < entries.size(); ++j) {
|
||||
auto const x = entries[j];
|
||||
auto const y = Next(x);
|
||||
entries[j] = y;
|
||||
patterns[j] = patterns[j] * 19 + y%10 + 9 - x%10;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 3; i < 2'000; ++i) {
|
||||
for (std::size_t j = 0; j < entries.size(); ++j) {
|
||||
auto const x = entries[j];
|
||||
auto const y = Next(x);
|
||||
entries[j] = y;
|
||||
auto const p = patterns[j] % (19 * 19 * 19) * 19 + y%10 + 9 - x%10;
|
||||
patterns[j] = p;
|
||||
if (!seen[j * 19 * 19 * 19 * 19 + p]) {
|
||||
seen[j * 19 * 19 * 19 * 19 + p] = true;
|
||||
counts[p] += y%10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto const p1 = std::accumulate(begin(entries), end(entries), std::uint64_t{0});
|
||||
auto const p2 = *std::max_element(begin(counts), end(counts));
|
||||
return {p1, p2};
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
auto Main(std::istream & in, std::ostream & out) -> void
|
||||
{
|
||||
auto entries = Parse(in);
|
||||
auto const [p1, p2] = Solve(std::move(entries));
|
||||
out << "Part 1: " << p1 << "\n"
|
||||
<< "Part 2: " << p2 << "\n";
|
||||
}
|
5
2024/CMakeLists.txt
Normal file
5
2024/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
add_executable(2024_07 07.cpp)
|
||||
target_link_libraries(2024_07 aocpp Boost::headers)
|
||||
|
||||
add_executable(2024_22 22.cpp)
|
||||
target_link_libraries(2024_22 aocpp)
|
@ -35,3 +35,4 @@ add_subdirectory(2020)
|
||||
add_subdirectory(2021)
|
||||
add_subdirectory(2022)
|
||||
add_subdirectory(2023)
|
||||
add_subdirectory(2024)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <boost/spirit/home/qi.hpp>
|
||||
#include <boost/fusion/include/boost_tuple.hpp>
|
||||
|
||||
namespace aocpp {
|
||||
|
||||
@ -46,6 +47,20 @@ auto ParseGrammar_(G const& grammar, std::istream & in) -> typename G::start_typ
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename P, typename R>
|
||||
auto ParseSimple(std::istream& in, P p, R & result) -> void
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
auto const content = std::string{std::istreambuf_iterator{in}, {}};
|
||||
qi::rule<std::string::const_iterator, R()> r { std::move(p) };
|
||||
auto it = content.begin();
|
||||
auto const end = content.end();
|
||||
bool success = qi::parse(it, end, r, result);
|
||||
if (!success || it != end) {
|
||||
throw std::runtime_error("Parsing failed or input was not fully consumed.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user