aocpp/2017/22.cpp
2024-09-02 14:12:42 -07:00

133 lines
2.7 KiB
C++

#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <stdexcept>
#include <unordered_map>
#include <unordered_set>
#include <doctest.h>
#include <aocpp/Grid.hpp>
#include <aocpp/Startup.hpp>
#include <aocpp/Coord.hpp>
auto Part1(aocpp::Grid const &input) -> std::int64_t
{
std::unordered_set<aocpp::Coord> infected;
// Initialize set of infected locations
input.each([&infected](auto const pos, auto const cell)
{
if (cell == '#')
{
infected.insert(pos);
} });
// Start in the middle
aocpp::Coord pos;
pos.x = input.Cols() / 2;
pos.y = input.Rows() / 2;
// Start going "up"
aocpp::Coord vel{.x = 0, .y = -1};
// Count the number of iterations that cause an infection
std::uint64_t infections = 0;
for (int i = 0; i < 10'000; ++i)
{
auto const it = infected.find(pos);
if (it == end(infected))
{
// was clean
vel = CCW(vel); // turn "left"
infected.insert(pos); // infect
infections++;
}
else
{
// was infected
vel = CW(vel); // turn "right"
infected.erase(it); // clean
}
pos += vel; // advance
}
return infections;
}
auto Part2(aocpp::Grid const &input) -> std::int64_t
{
std::unordered_map<aocpp::Coord, char> cells;
// Initialize set of infected locations
input.each([&cells](auto const pos, auto const cell)
{
if (cell == '#')
{
cells.try_emplace(pos, '#');
} });
// Start in the middle
aocpp::Coord pos;
pos.x = input.Cols() / 2;
pos.y = input.Rows() / 2;
// Start going "up"
aocpp::Coord vel{.x = 0, .y = -1};
// Count the number of iterations that cause an infection
std::uint64_t infections = 0;
for (int i = 0; i < 10'000'000; ++i)
{
auto const [it, added] = cells.try_emplace(pos, 'W'); // clean becomes weakened
if (added)
{
// already inserted 'W'
vel = CCW(vel); // turn "left"
}
else
{
switch (it->second)
{
case 'W':
// no turn
it->second = '#';
infections++;
break;
case '#':
vel = CW(vel); // turn "right"
it->second = 'F';
break;
case 'F':
vel = Turn180(vel);
cells.erase(it); // clean
break;
default:
throw std::logic_error{"unexpected cell in steps"};
}
}
pos += vel; // advance
}
return infections;
}
TEST_SUITE("2017-22 examples")
{
TEST_CASE("part 1")
{
}
TEST_CASE("part 2")
{
}
}
auto Main(std::istream &in, std::ostream &out) -> void
{
auto const input = aocpp::Grid::Parse(in);
out << "Part 1: " << Part1(input) << std::endl;
out << "Part 2: " << Part2(input) << std::endl;
}