137 lines
3.0 KiB
C++
137 lines
3.0 KiB
C++
#include "common/aoc.h"
|
|
|
|
namespace y2016::day22
|
|
{
|
|
struct Fs
|
|
{
|
|
int used;
|
|
int avail;
|
|
|
|
bool operator==(const Fs& other) const
|
|
{
|
|
return used == other.used && avail == other.avail;
|
|
}
|
|
};
|
|
|
|
REGISTER_DAY(2016, Day22, Array2D<Fs>, int);
|
|
|
|
REGISTER_TEST_EXAMPLE(2016, Day22, ExampleInput, 1, 7);
|
|
REGISTER_TEST(2016, Day22, Input, 1, 1024);
|
|
REGISTER_TEST_EXAMPLE(2016, Day22, ExampleInput, 2, 7);
|
|
REGISTER_TEST(2016, Day22, Input, 2, 230);
|
|
|
|
READ_INPUT(input)
|
|
{
|
|
std::vector<std::pair<std::pair<int, int>, Fs>> fss;
|
|
Array2D<Fs> vec{};
|
|
std::string str;
|
|
getline(input, str);
|
|
getline(input, str);
|
|
int maxX = 0;
|
|
int maxY = 0;
|
|
while (getline(input, str))
|
|
{
|
|
// /dev/grid/node-x0-y0 91T 71T 20T 78%
|
|
Fs fs;
|
|
std::stringstream ss{str};
|
|
int dummy;
|
|
int x;
|
|
int y;
|
|
ss >> "/dev/grid/node-x" >> x >> "-y" >> y >> dummy >> "T" >> fs.used >> "T" >> fs.avail >> "T";
|
|
fss.emplace_back(std::pair{std::pair{x, y}, fs});
|
|
maxX = std::max(maxX, x);
|
|
maxY = std::max(maxY, y);
|
|
}
|
|
vec = Array2D<Fs>{maxX + 1, maxY + 1};
|
|
for (const auto& [pos, fs] : fss)
|
|
{
|
|
vec.Set(pos.first, pos.second, fs);
|
|
}
|
|
return vec;
|
|
}
|
|
|
|
struct State
|
|
{
|
|
Index2D goal;
|
|
Index2D empty;
|
|
|
|
bool operator<(const State& other) const
|
|
{
|
|
if (goal != other.goal)
|
|
return goal < other.goal;
|
|
return empty < other.empty;
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const State& state)
|
|
{
|
|
return os << state.goal << " " << state.empty;
|
|
}
|
|
};
|
|
|
|
std::vector<std::pair<int, State>> Branch(const Array2D<Fs>& initial, const State& state)
|
|
{
|
|
std::vector<std::pair<int, State>> states{};
|
|
Fs emptyFs = initial.Get(state.empty);
|
|
std::vector<Index2D> neighbors = initial.GetNeighbors(state.empty, false);
|
|
for (const auto& neighbor : neighbors)
|
|
{
|
|
if (initial.Get(neighbor).used < 400)
|
|
{
|
|
State newState = state;
|
|
if (neighbor == state.goal)
|
|
newState.goal = state.empty;
|
|
newState.empty = neighbor;
|
|
states.emplace_back(1, newState);
|
|
}
|
|
}
|
|
return states;
|
|
}
|
|
|
|
bool Goal(const Array2D<Fs>& initial, const State& state)
|
|
{
|
|
return state.goal == Index2D{0, 0};
|
|
}
|
|
|
|
int Heuristic(const Array2D<Fs>& initial, const State& state)
|
|
{
|
|
return state.goal.x + state.goal.y;
|
|
}
|
|
|
|
OUTPUT1(input)
|
|
{
|
|
int count = 0;
|
|
for (const auto& val : input)
|
|
{
|
|
if (val.used == 0)
|
|
continue;
|
|
for (const auto& val2 : input)
|
|
{
|
|
if (val == val2)
|
|
continue;
|
|
if (val.used <= val2.avail)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
OUTPUT2(input)
|
|
{
|
|
State state;
|
|
state.goal = Index2D{input.width - 1, 0};
|
|
for (int i = 0; i < input.height; i++)
|
|
{
|
|
for (int j = 0; j < input.width; j++)
|
|
{
|
|
if (input.Get(j, i).used == 0)
|
|
{
|
|
state.empty = Index2D{j, i};
|
|
}
|
|
}
|
|
}
|
|
return Helper::AStar(input, state, Heuristic, Branch, Goal);
|
|
}
|
|
}
|