176 lines
3.1 KiB
C++
176 lines
3.1 KiB
C++
#include <algorithm>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <set>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <unistd.h>
|
|
#include <vector>
|
|
|
|
struct Position {
|
|
// NOTE(dev): Could do enum empty/reached/blocked, but I'm not interested.
|
|
bool blocked = false;
|
|
bool reached = false;
|
|
};
|
|
|
|
enum Direction {
|
|
UP = 0,
|
|
RIGHT,
|
|
DOWN,
|
|
LEFT
|
|
};
|
|
|
|
struct Player {
|
|
std::pair<int, int> location;
|
|
Direction direction = Direction::UP;
|
|
};
|
|
|
|
int main()
|
|
{
|
|
const std::string filename = "data.txt";
|
|
std::ifstream ifs(filename);
|
|
if(!ifs.is_open())
|
|
{
|
|
std::cerr << "Missing " << filename << "." << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
unsigned long total = 0;
|
|
unsigned long total_pt2 = 0;
|
|
|
|
std::map<std::pair<int, int>, Position> level;
|
|
Player player;
|
|
|
|
int max_x = 0;
|
|
int max_y = 0;
|
|
bool first_row = true;
|
|
int y = 0;
|
|
|
|
auto DebugPrint = [&]()
|
|
{
|
|
std::cout << std::endl;
|
|
for(auto y = 0; y < max_y; ++y)
|
|
{
|
|
for(auto x = 0; x < max_x; ++x)
|
|
{
|
|
if(player.location.first == x && player.location.second == y)
|
|
{
|
|
switch(player.direction)
|
|
{
|
|
case Direction::UP:
|
|
std::cout << "^";
|
|
break;
|
|
case Direction::RIGHT:
|
|
std::cout << ">";
|
|
break;
|
|
case Direction::DOWN:
|
|
std::cout << "v";
|
|
break;
|
|
case Direction::LEFT:
|
|
std::cout << "<";
|
|
break;
|
|
};
|
|
}
|
|
else
|
|
{
|
|
const auto &pos = level[{x, y}];
|
|
if(pos.reached)
|
|
std::cout << "X";
|
|
else if(pos.blocked)
|
|
std::cout << "#";
|
|
else
|
|
std::cout << ".";
|
|
}
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
};
|
|
|
|
// Parse Input
|
|
for(std::string line; std::getline(ifs, line); )
|
|
{
|
|
if(line == "")
|
|
continue;
|
|
|
|
int x = 0;
|
|
for(const char &value : line)
|
|
{
|
|
Position pos;
|
|
if(value == '#')
|
|
pos.blocked = true;
|
|
if(value == '^') // always up?
|
|
{
|
|
pos.reached = true;
|
|
player.location = {x, y};
|
|
}
|
|
|
|
level[{x, y}] = pos;
|
|
|
|
++x;
|
|
}
|
|
if(first_row)
|
|
{
|
|
max_x = x;
|
|
first_row = false;
|
|
}
|
|
++y;
|
|
}
|
|
max_y = y;
|
|
|
|
// DEBUG:
|
|
DebugPrint();
|
|
|
|
std::cout << std::endl;
|
|
|
|
// while(player.location.first >= 0 && player.location.first < max_x &&
|
|
// player.location.second >= 0 && player.location.second < max_y)
|
|
while(true)
|
|
{
|
|
std::pair<int, int> next_location = player.location;
|
|
switch(player.direction)
|
|
{
|
|
case Direction::UP:
|
|
--next_location.second;
|
|
break;
|
|
case Direction::RIGHT:
|
|
++next_location.first;
|
|
break;
|
|
case Direction::DOWN:
|
|
++next_location.second;
|
|
break;
|
|
case Direction::LEFT:
|
|
--next_location.first;
|
|
break;
|
|
};
|
|
|
|
if(!level.contains(next_location))
|
|
{
|
|
player.location = next_location;
|
|
break;
|
|
}
|
|
if(level[next_location].blocked)
|
|
player.direction = static_cast<Direction>(((int(player.direction)) + 1) % 4);
|
|
else
|
|
{
|
|
level[next_location].reached = true;
|
|
player.location = next_location;
|
|
// DebugPrint();
|
|
// usleep(20000);
|
|
}
|
|
}
|
|
|
|
DebugPrint();
|
|
|
|
for(auto y = 0; y < max_y; ++y)
|
|
for(auto x = 0; x < max_x; ++x)
|
|
if(level[{x,y}].reached)
|
|
++total;
|
|
|
|
std::cout << std::endl;
|
|
std::cout << " Total: " << total << std::endl;
|
|
std::cout << "PT2 Total: " << total_pt2 << std::endl;
|
|
|
|
return 0;
|
|
}
|