This commit is contained in:
Eric Mertens 2023-04-07 09:45:55 -07:00
parent 930a02622d
commit a38a105e6f
6 changed files with 62 additions and 39 deletions

View File

@ -2,6 +2,7 @@
#include <cstdint>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <variant>
#include <vector>

View File

@ -4,6 +4,7 @@
#include <iostream>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <tuple>
#include <unordered_set>
#include <vector>

View File

@ -12,6 +12,7 @@
#include <cstdint>
#include <iostream>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <tuple>
@ -90,8 +91,8 @@ struct Room {
/// * Valve **name** has flow rate= **number** ; tunnel leads to valve **name**
auto Parse(std::istream & in) -> std::vector<Room>
{
std::vector<Room> result;
std::string line;
auto result = std::vector<Room>{};
auto line = std::string{};
while (std::getline(in, line)) {
using namespace qi::labels;
using It = std::string::const_iterator;
@ -108,8 +109,8 @@ auto Parse(std::istream & in) -> std::vector<Room>
" " >>
(name % ", ") [ phx::bind(&Room::connections, _val) = _1 ];
It b = line.begin();
It const e = line.end();
auto b = line.cbegin();
auto const e = line.cend();
result.emplace_back();
if (!qi::parse(b, e, room_description, result.back()) || b != e) {
throw std::runtime_error{"bad input line"};
@ -138,15 +139,15 @@ auto GenerateDistances(
std::vector<Room> const& rooms
) -> std::pair<std::size_t, distance_array<std::uint64_t>>
{
auto const N {rooms.size()};
auto const N = rooms.size();
// Associate the names and indexes of each room
std::unordered_map<std::string, std::size_t> names;
for (auto [i,room] : rooms | boost::adaptors::indexed()) {
for (auto const [i,room] : boost::adaptors::index(rooms)) {
names[room.name] = i;
}
distance_array<std::uint64_t> distances{boost::extents[N][N]};
auto distances = distance_array<std::uint64_t>{boost::extents[N][N]};
for (auto const i : boost::irange(rooms.size())) {
auto di = distances[i];
@ -201,13 +202,15 @@ auto Routes(
}
// Maximal flow seen at each set of open valves
std::unordered_map<Valves, std::uint64_t> result;
auto result = std::unordered_map<Valves, std::uint64_t>{};
// Remaining states for depth first search
std::vector<State> states {{initial_time, 0, start, {}}};
auto states = std::stack<State>{};
states.push({initial_time, 0, start, {}});
while (!states.empty()) {
auto const state = states.back();
states.pop_back();
auto const state = states.top();
states.pop();
if (auto & best = result[state.valves]; best < state.flow) {
best = state.flow;
@ -215,7 +218,7 @@ auto Routes(
auto const distances_i = distances[state.location];
for (auto const [j, room] : rooms | boost::adaptors::indexed()) {
for (auto const [j, room] : boost::adaptors::index(rooms)) {
// don't revisit a valve
if (state.valves.test(j)) { continue; }
@ -229,7 +232,7 @@ auto Routes(
auto valves = state.valves;
valves.set(j);
states.push_back({time, flow, static_cast<std::size_t>(j), valves});
states.push({time, flow, static_cast<std::size_t>(j), valves});
}
}
@ -265,7 +268,7 @@ auto Part2(
auto const routes = Routes(start, 26, rooms, distances);
auto const end = routes.end();
std::uint64_t best {0};
auto best = std::uint64_t{0};
for (auto it1 = routes.begin(); it1 != end; ++it1) {
for (auto it2 = std::next(it1); it2 != end; ++it2) {
// only consider pairs that have disjoint sets of valves
@ -285,7 +288,7 @@ auto Part2(
auto Main(std::istream & in, std::ostream & out) -> void
{
auto rooms = Parse(in);
auto const n = FlowsFirst(rooms);
auto const n = FlowsFirst(rooms); // reorders rooms
auto const [start, distances] = GenerateDistances(rooms);
rooms.resize(n); // forget about the rooms with no flow
out << "Part 1: " << Part1(start, rooms, distances) << std::endl;
@ -306,13 +309,13 @@ Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II
)"};
std::ostringstream out;
auto out = std::ostringstream{};
Main(in, out);
CHECK(out.str() == "Part 1: 1651\nPart 2: 1707\n");
}
TEST_CASE("shortest path") {
distance_array<int> distances{boost::extents[4][4]};
auto distances = distance_array<int>{boost::extents[4][4]};
std::fill_n(distances.data(), distances.num_elements(), 100);
distances[0][2] = -2;

View File

@ -4,6 +4,7 @@
#include <iostream>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <tuple>
@ -24,12 +25,14 @@ using Coord = aocpp::Vec<std::int64_t, 3>;
/// @return set of coordinates
auto Parse(std::istream & in) -> std::set<Coord>
{
std::set<Coord> result;
std::string line;
auto result = std::set<Coord>{};
auto line = std::string{};
while (in >> line) {
Coord x;
if (3 != std::sscanf(line.c_str(), "%lld,%lld,%lld\n", &x[0], &x[1], &x[2]))
auto x = Coord{};
if (3 != std::sscanf(line.c_str(), "%lld,%lld,%lld\n", &x[0], &x[1], &x[2])) {
throw std::runtime_error{"bad input line"};
}
result.insert(x);
}
return result;
@ -37,8 +40,8 @@ auto Parse(std::istream & in) -> std::set<Coord>
auto Part1(std::set<Coord> const& obj) -> std::size_t
{
std::size_t result {0};
for (auto && x : obj) {
auto result = std::size_t{0};
for (auto const& x : obj) {
x.EachNeighbor([&](Coord const& y) {
if (!obj.contains(y)) result++;
});
@ -49,21 +52,24 @@ auto Part1(std::set<Coord> const& obj) -> std::size_t
auto Part2(std::set<Coord> const& obj) -> std::size_t
{
auto [lo, hi] = Coord::BoundingBox(obj.begin(), obj.end());
lo -= Coord(1);
hi += Coord(1);
lo -= Coord{1};
hi += Coord{1};
std::set<Coord> seen {lo};
std::vector<Coord> work {lo};
std::size_t result {0};
auto seen = std::set<Coord>{};
auto work = std::stack<Coord>{};
auto result = std::size_t{0};
work.push(lo);
seen.insert(lo);
while (!work.empty()) {
auto x = work.back();
work.pop_back();
auto const x = work.top();
work.pop();
x.EachNeighbor([&, lo=lo, hi=hi](Coord const& y) {
if (obj.contains(y)) {
result++;
} else if (y.InRange(lo, hi) && seen.insert(y).second) {
work.push_back(y);
work.push(y);
}
});
}
@ -98,7 +104,7 @@ TEST_SUITE("2022-12 examples") {
auto Main(std::istream & in, std::ostream & out) -> void
{
auto const obj {Parse(in)};
auto const obj = Parse(in);
out << "Part 1: " << Part1(obj) << std::endl;
out << "Part 2: " << Part2(obj) << std::endl;
}

View File

@ -4,6 +4,7 @@
#include <iterator>
#include <numeric>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>
@ -24,7 +25,7 @@ using Input = std::vector<std::int64_t>;
/// @return outer list of elves, inner lists of calories
auto Parse(std::istream & in) -> Input
{
Input result;
auto result = Input{};
using It = std::istream_iterator<std::int64_t>;
std::copy<It>(in, {}, std::back_inserter(result));
return result;
@ -33,7 +34,17 @@ auto Parse(std::istream & in) -> Input
auto Solve(Input const& input, std::size_t const rounds) -> std::int64_t
{
auto const len = input.size();
std::vector<std::size_t> fwds(len), bwds(len);
auto fwds = std::vector<std::size_t>(len);
auto bwds = std::vector<std::size_t>(len);
if (len == 0) {
throw std::runtime_error{"Input too small"};
}
auto const zero_it = std::find(input.begin(), input.end(), 0);
if (zero_it == input.end()) {
throw std::runtime_error{"no zero element in input"};
}
std::iota(fwds.begin(), fwds.end()-1, 1); fwds.back() = 0;
std::iota(bwds.begin()+1, bwds.end(), 0); bwds.front() = len-1;
@ -67,8 +78,8 @@ auto Solve(Input const& input, std::size_t const rounds) -> std::int64_t
}
}
std::int64_t sum {0};
auto cursor = std::distance(input.begin(), std::find(input.begin(), input.end(), 0));
auto sum = std::int64_t{0};
auto cursor = std::distance(input.begin(), zero_it);
for (auto const _ : boost::irange(3)) {
for (auto const _ : boost::irange(1000)) {
cursor = fwds[cursor];
@ -86,7 +97,7 @@ auto Part1(Input const& input) -> std::int64_t
auto Part2(Input input) -> std::int64_t
{
for (auto& x : input) { x *= 811589153; }
for (auto& x : input) { x *= 811'589'153; }
return Solve(input, 10);
}
@ -104,13 +115,13 @@ TEST_SUITE("2022-20 examples") {
"4\n"};
auto input = Parse(in);
CHECK(3 == Part1(input));
CHECK(1623178306 == Part2(input));
CHECK(1623178306 == Part2(std::move(input)));
}
}
auto Main(std::istream & in, std::ostream & out) -> void
{
auto input {Parse(in)};
auto input = Parse(in);
out << "Part 1: " << Part1(input) << std::endl;
out << "Part 2: " << Part2(std::move(input)) << std::endl;
}

View File

@ -1,6 +1,7 @@
#include <cstdint>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <variant>