Skip to content

Commit

Permalink
day 15 part 2, it works but it's ugly
Browse files Browse the repository at this point in the history
  • Loading branch information
K20shores committed Dec 16, 2024
1 parent 944a23d commit 38c9667
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 45 deletions.
4 changes: 2 additions & 2 deletions 2024/include/aoc/2024/pos.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ struct Pos
int64_t x = 0;
int64_t y = 0;

Pos operator+(const Pos other)
Pos operator+(const Pos other) const
{
return {.x = this->x + other.x, .y = this->y + other.y};
}

Pos operator-(const Pos &other)
Pos operator-(const Pos &other) const
{
return {.x = this->x - other.x, .y = this->y - other.y};
}
Expand Down
251 changes: 208 additions & 43 deletions 2024/src/day15.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,74 @@
#include <benchmark/benchmark.h>
#include <format>
#include <aoc/2024/pos.h>
#include <queue>

struct Data {
struct Data
{
std::vector<std::string> grid;
std::vector<Pos> directions;
Pos robot;
};

bool in_bounds(const Data &data, const Pos &p)
bool in_bounds(const std::vector<std::string> &grid, const Pos &p)
{
return p.x >= 0 && p.y >= 0 && p.x < data.grid[0].size() && p.y < data.grid.size();
return p.x >= 0 && p.y >= 0 && p.x < grid[0].size() && p.y < grid.size();
};

int64_t score(std::vector<std::string> &grid)
{
int64_t score = 0;
for(size_t j = 0; j < grid.size(); ++j) {
for(size_t i = 0; i < grid[j].size(); ++i) {
if (grid[j][i] == 'O') {
for (size_t j = 0; j < grid.size(); ++j)
{
for (size_t i = 0; i < grid[j].size(); ++i)
{
if (grid[j][i] == 'O' || grid[j][i] == '[')
{
score += 100 * j + i;
}
}
}
return score;
}

Pos find_free_space(const std::vector<std::string> &grid, const Pos &start, const Pos &dir)
{
Pos open_space = start + dir;
while (in_bounds(grid, open_space) && grid[open_space.y][open_space.x] != '#')
{
if (grid[open_space.y][open_space.x] == '.')
{
return open_space;
}
open_space += dir;
}
return {.x = -1, .y = -1};
}

int64_t part1(const Data &data)
{
auto grid = data.grid;
Pos cur = data.robot;
for(auto dir : data.directions) {
for (auto dir : data.directions)
{
Pos next = cur + dir;
if (in_bounds(data, next)) {
if (in_bounds(grid, next))
{
char c = grid[next.y][next.x];
if (c == '.') {
if (c == '.')
{
grid[next.y][next.x] = grid[cur.y][cur.x];
grid[cur.y][cur.x] = '.';
cur = next;
}
else if (c == 'O') {
Pos open_space = next + dir;
bool open = false;
while (in_bounds(data, open_space) && grid[open_space.y][open_space.x] != '#') {
if (grid[open_space.y][open_space.x] == '.') {
open = true;
break;
}
open_space += dir;
}
else if (c == 'O')
{
Pos open_space = find_free_space(grid, next, dir);

if (open) {
while(open_space != next) {
if (open_space.x != -1)
{
while (open_space != next)
{
Pos before = open_space - dir;
grid[open_space.y][open_space.x] = grid[before.y][before.x];
grid[before.y][before.x] = '.';
Expand All @@ -74,9 +91,151 @@ int64_t part1(const Data &data)
return score(grid);
}

std::vector<std::string> transform_grid(const std::vector<std::string> &grid)
{
std::vector<std::string> new_grid;
for (auto &row : grid)
{
std::string new_row = "";
for (auto &c : row)
{
if (c == '.')
{
new_row += "..";
}
else if (c == '#')
{
new_row += "##";
}
else if (c == 'O')
{
new_row += "[]";
}
else if (c == '@')
{
new_row += "@.";
}
}
new_grid.push_back(new_row);
}
return new_grid;
}

void print_grid(const std::vector<std::string> &grid)
{
for (auto &row : grid)
{
std::cout << row << std::endl;
}
std::cout << std::endl;
}

int64_t part2(const Data &data)
{
return 0;
auto grid = transform_grid(data.grid);
Pos cur = {.x = data.robot.x * 2, .y = data.robot.y};
for (auto dir : data.directions)
{
Pos next = cur + dir;
if (in_bounds(grid, next))
{
char c = grid[next.y][next.x];
if (c == '.')
{
grid[next.y][next.x] = grid[cur.y][cur.x];
grid[cur.y][cur.x] = '.';
cur = next;
}
else if (c == '[' || c == ']')
{
// open space, ending space
std::vector<std::pair<Pos, Pos>> open_spaces;
std::queue<std::pair<Pos, Pos>> q;
q.push({next, next});

if (dir == N || dir == S)
{
if (c == '[')
{
q.push({next + E, next + E});
}
else
{
q.push({next + W, next + W});
}
}

bool open = true;
while (!q.empty())
{
auto [start, end] = q.front();
q.pop();
Pos open_space = start + dir;
while (in_bounds(grid, open_space) && grid[open_space.y][open_space.x] != '#')
{
if (grid[open_space.y][open_space.x] == '.')
{
break;
}
if (grid[open_space.y][open_space.x] == '[' && (dir == N || dir == S))
{
q.push({open_space + E, open_space + E});
}
if (grid[open_space.y][open_space.x] == ']' && (dir == N || dir == S))
{
q.push({open_space + W, open_space + W});
}
open_space += dir;
}
if (in_bounds(grid, open_space) && grid[open_space.y][open_space.x] != '#')
{
start = open_space;
open_spaces.push_back({start, end});
}
else
{
open = false;
break;
}
}

// sort first by y, then by x
// and if I am going north, put the highest y first
// if I am going north, put the lowest y first
std::sort(open_spaces.begin(), open_spaces.end(), [&](const auto &a, const auto &b)
{
if (a.second.y != b.second.y) {
if (dir == N) {
return a.second.y < b.second.y;
}
return a.second.y > b.second.y;
}
return a.second.x < b.second.x; });

if (open)
{
for (auto &[open_space, end] : open_spaces)
{
while (open_space != end)
{
if (grid[open_space.y][open_space.x] == '.')
{
Pos before = open_space - dir;
grid[open_space.y][open_space.x] = grid[before.y][before.x];
grid[before.y][before.x] = '.';
}
open_space -= dir;
}
}

grid[next.y][next.x] = grid[cur.y][cur.x];
grid[cur.y][cur.x] = '.';
cur = next;
}
}
}
}
return score(grid);
}

Data parse()
Expand All @@ -98,29 +257,33 @@ Data parse()
grid = false;
continue;
}
if (grid) {
if (grid)
{
auto robot = line.find('@');
if (robot != std::string::npos) {
if (robot != std::string::npos)
{
data.robot = {.x = static_cast<int64_t>(robot), .y = j};
}
data.grid.push_back(line);
}
else {
for(auto c : line) {
else
{
for (auto c : line)
{
switch (c)
{
case '^':
data.directions.push_back(N);
break;
case 'v':
data.directions.push_back(S);
break;
case '<':
data.directions.push_back(W);
break;
case '>':
data.directions.push_back(E);
break;
case '^':
data.directions.push_back(N);
break;
case 'v':
data.directions.push_back(S);
break;
case '<':
data.directions.push_back(W);
break;
case '>':
data.directions.push_back(E);
break;
}
}
}
Expand Down Expand Up @@ -166,22 +329,24 @@ int main(int argc, char **argv)
Data data = parse();

int64_t answer1 = 1475249;
int64_t answer2 = 0;
int64_t answer2 = 1509724;

auto first = part1(data);
std::cout << "Part 1: " << first << std::endl;

auto second = part2(data);
std::cout << "Part 2: " << second << std::endl;

first != answer1 ? throw std::runtime_error("Part 1 incorrect") : nullptr;
second != answer2 ? throw std::runtime_error("Part 2 incorrect") : nullptr;

for (int i = 1; i < argc; ++i) {
if (std::string(argv[i]) == "--benchmark") {
for (int i = 1; i < argc; ++i)
{
if (std::string(argv[i]) == "--benchmark")
{
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
return 0;
}
}
}
}

0 comments on commit 38c9667

Please sign in to comment.