advent_of_code/2022/12/main.cpp

116 lines
3.3 KiB
C++
Raw Normal View History

2022-12-12 19:22:26 +00:00
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
struct Point {
size_t x;
size_t y;
};
struct Position {
int elevation;
bool visited;
};
struct MazeInput {
std::vector<std::vector<Position>> maze;
Point start;
};
MazeInput getMaze( std::ifstream &file ) {
std::vector<std::vector<Position>> maze{};
Point start{};
std::string str;
int y = -1;
while ( std::getline( file, str ) ) {
y++;
maze.emplace_back();
int x = -1;
for ( auto &c : str ) {
x++;
switch ( c ) {
case 'S':
maze.back().push_back( { 1, false } );
start.y = y;
start.x = x;
break;
case 'E':
maze.back().push_back( { 27, false } );
break;
default:
maze.back().push_back( { c - 'a' + 1, false } );
}
}
}
return { maze, start };
}
struct BFSEntry {
Point point;
int path_len;
};
int BFS( std::vector<std::vector<Position>> &maze, const Point &start ) {
std::deque<BFSEntry> entries = { { start, 0 } };
maze[start.y][start.x].visited = true;
while ( !entries.empty() ) {
for ( int y = -1; y < 2; y++ ) {
for ( int x = -1; x < 2; x++ ) {
if ( y != 0 && x != 0 ) {
continue;
}
Point next_point = { entries.front().point.x + x,
entries.front().point.y + y };
if ( next_point.y < 0 || next_point.y >= maze.size() ||
next_point.x < 0 || next_point.x >= maze[0].size() ) {
continue;
}
if ( !maze[next_point.y][next_point.x].visited &&
( maze[next_point.y][next_point.x].elevation -
maze[entries.front().point.y][entries.front().point.x].elevation ) <= 1 ) {
if ( maze[next_point.y][next_point.x].elevation == 27 ) {
return entries.front().path_len + 1;
}
maze[next_point.y][next_point.x].visited = true;
entries.push_back(
{ next_point, 1 + entries.front().path_len } );
}
}
}
entries.pop_front();
}
return -1;
}
int part1( const std::vector<std::vector<Position>> &maze,
const Point &start ) {
auto maze_copy = maze;
return BFS( maze_copy, start );
}
int part2( const std::vector<std::vector<Position>> &maze ) {
int min = -1;
for ( size_t y = 0; y < maze.size(); y++ ) {
for ( size_t x = 0; x < maze[0].size(); x++ ) {
if ( maze[y][x].elevation == 1 ) {
auto maze_copy = maze;
auto path = BFS( maze_copy, { x, y } );
if ( path != -1 && ( path < min || min == -1 ) ) {
min = path;
}
}
}
}
return min;
}
int main() {
std::ifstream input_file( "input" );
auto input = getMaze( input_file );
std::cout << "Part 1 result is \033[91;1m"
<< part1( input.maze, input.start ) << "\033[0m." << std::endl;
std::cout << "Part 2 result is \033[91;1m" << part2( input.maze )
<< "\033[0m." << std::endl;
}