I went rock climbing today. Hung out with a friend I hadn't seen in a long time, and their partner who I only met breifly before. It was a nice, active diversion from all of the stress and work I've had lately.
A falling sand puzzle! Some basic physics. Seems kinda fun to try and simulate, and see what kind of fun structures the input might have in store. I'm excited for this one actually.
First thing first, parse it, and figure out the range of values. It'll help a bit figuring out how much of a surface I need to actually simulate.
vector<string> split(string s, string delim)
{
vector<string> output;
while (s.find(delim) != string::npos)
{
size_t pos = s.find(delim);
output.push_back(s.substr(0, pos));
s.erase(0, pos + delim.length());
}
return output;
}
So odd that C++ doesn't have its own string split function - nearly every other language has something similar. I've been working around it up to this point, but I'll probably just nab this bit of code for a lot of future.
X: 447 - 515
Y: 13 - 168
That range seems reasonable. 68x155 grid. Not that big of a deal. Now I know the bounds, I can just draw the lines in the bounds.
// Prepare and draw map
for (int i = 0; i <= ymax; i++)
{
string s = "";
for (int j = xmin; j <= xmax; j++) s += ".";
map.push_back(s);
}
for (Line line: lines)
{
Coord dir, from, to = line[0];
for (int i = 1; i < line.size(); i++)
{
from = to;
to = line[i];
if (from.first < to.first) dir = Coord( 1, 0);
else if (from.first > to.first) dir = Coord(-1, 0);
else if (from.second < to.second) dir = Coord( 0, 1);
else if (from.second > to.second) dir = Coord( 0,-1);
map[from.second][from.first-xmin] = '#';
while (from != to)
{
map[from.second][from.first-xmin] = '#';
from.first += dir.first;
from.second += dir.second;
}
}
}
Map prepared, time for physics... I guess?
// Perform physics
int count = 0;
while(true)
{
int grain = START_X - xmin;
// Drop grain
int i = 0;
for (; i < map.size(); i++)
{
// Check if fallen off map bottom
if (i+1 >= map.size()) { cout << "Total grains: " << count << endl; return 0; }
// Check directly below
if (map[i+1][grain] == '.') continue;
// Check down-left
if (map[i+1][grain-1] == '.' ) { grain--; continue; }
// Check down-right
if (map[i+1][grain+1] == '.') { grain++; continue; }
break;
}
map[i][grain] = 'o';
count++;
}
Okay, Part 2 is eazy enough. It's just an extra floor two spaces below the existing map, nothing inbetween. It should be easy enough... eugh, except I just realized the far X and Y are now just going to be existant. So now it's going to be something like a 1000x158 grid. I guess the optimizations I initially did are going away.
// Add extra space and floor
string hardFloor = "";
for (int j = 0; j <= xmax*2; j++) hardFloor += "#";
map.push_back(hardFloor);