parent
86120c01a1
commit
1e991c1f77
2 changed files with 247 additions and 3 deletions
@ -1,9 +1,225 @@ |
||||
#include "Day10.h" |
||||
|
||||
Result Day10::Task1() { |
||||
return Day::Task1(); |
||||
Map map = parseMap(); |
||||
|
||||
Coord start = getStart(); |
||||
|
||||
vector<pair<Coord, vector<Tile>>> neighbours = { |
||||
{{start.x + 1, start.y}, {NORTH_WEST, SOUTH_WEST, HORIZONTAL}}, |
||||
{{start.x - 1, start.y}, {NORTH_EAST, SOUTH_EAST, HORIZONTAL}}, |
||||
{{start.x, start.y + 1}, {NORTH_WEST, NORTH_EAST, VERTICAL}}, |
||||
{{start.x, start.y - 1}, {SOUTH_WEST, SOUTH_EAST, VERTICAL}}, |
||||
}; |
||||
|
||||
Coord current {}; |
||||
|
||||
for (const auto &[coord, types] : neighbours) |
||||
for (const auto &type : types) |
||||
if (map.at(coord) == type) |
||||
current = coord; |
||||
|
||||
Coord previous = start; |
||||
|
||||
vector<Coord> loop = {start}; |
||||
|
||||
while (map.at(current) != START) { |
||||
loop.push_back(current); |
||||
Coord next = map.next(previous, current); |
||||
previous = current; |
||||
current = next; |
||||
} |
||||
|
||||
size_t distance = loop.size() / 2; |
||||
|
||||
return to_string(distance); |
||||
} |
||||
|
||||
Result Day10::Task2() { |
||||
return Day::Task2(); |
||||
Map map = parseMap(); |
||||
|
||||
Coord start = getStart(); |
||||
|
||||
vector<pair<Coord, vector<Tile>>> neighbours = { |
||||
{{start.x + 1, start.y}, {NORTH_WEST, SOUTH_WEST, HORIZONTAL}}, |
||||
{{start.x - 1, start.y}, {NORTH_EAST, SOUTH_EAST, HORIZONTAL}}, |
||||
{{start.x, start.y + 1}, {NORTH_WEST, NORTH_EAST, VERTICAL}}, |
||||
{{start.x, start.y - 1}, {SOUTH_WEST, SOUTH_EAST, VERTICAL}}, |
||||
}; |
||||
|
||||
Coord current {}; |
||||
|
||||
for (const auto &[coord, types] : neighbours) |
||||
for (const auto &type : types) |
||||
if (map.at(coord) == type) |
||||
current = coord; |
||||
|
||||
Coord previous = start; |
||||
|
||||
vector<Coord> loop = {start}; |
||||
|
||||
while (map.at(current) != START) { |
||||
loop.push_back(current); |
||||
Coord next = map.next(previous, current); |
||||
previous = current; |
||||
current = next; |
||||
} |
||||
|
||||
vector<vector<bool>> mask(map.tiles.size(), vector<bool>(map.tiles[0].size(), false)); |
||||
for (const Coord &coord : loop) |
||||
mask[coord.y][coord.x] = true; |
||||
|
||||
map.replaceStart(loop); |
||||
|
||||
uint64 area = 0; |
||||
bool inside = false; |
||||
bool edgeEntryFromTop = false; |
||||
for (size_t y = 0; y < map.tiles.size(); y++){ |
||||
for (size_t x = 0; x < map.tiles[0].size(); x++){ |
||||
if (mask[y][x]){ |
||||
switch (map.at({x, y})) { |
||||
case VERTICAL: |
||||
inside = !inside; |
||||
break; |
||||
case NORTH_EAST: |
||||
edgeEntryFromTop = true; |
||||
break; |
||||
case SOUTH_EAST: |
||||
edgeEntryFromTop = false; |
||||
break; |
||||
case SOUTH_WEST: |
||||
if (edgeEntryFromTop) |
||||
inside = !inside; |
||||
break; |
||||
case NORTH_WEST: |
||||
if (!edgeEntryFromTop) |
||||
inside = !inside; |
||||
break; |
||||
case HORIZONTAL: |
||||
break; |
||||
default: |
||||
exit(1); |
||||
} |
||||
} else if (inside) |
||||
area++; |
||||
} |
||||
} |
||||
|
||||
return to_string(area); |
||||
} |
||||
|
||||
Day10::Map Day10::parseMap() const { |
||||
Map map; |
||||
for (const string &line : input){ |
||||
vector<Tile> row; |
||||
for (const char &c : line) |
||||
row.push_back(charToTile.at(c)); |
||||
map.tiles.push_back(row); |
||||
} |
||||
return map; |
||||
} |
||||
|
||||
Day10::Coord Day10::getStart() const { |
||||
for (size_t y = 0; y < input.size(); y++) |
||||
for (size_t x = 0; x < input[y].size(); x++) |
||||
if (input[y][x] == 'S') |
||||
return {x, y}; |
||||
cout << "No Start found!" << endl; |
||||
exit(1); |
||||
} |
||||
|
||||
Day10::Tile Day10::Map::at(const Day10::Coord &c) const { |
||||
if (c.y < 0 || c.y >= tiles.size() || |
||||
c.x < 0 || c.x >= tiles[0].size()) |
||||
return GROUND; |
||||
return tiles[c.y][c.x]; |
||||
} |
||||
|
||||
Day10::Coord Day10::Map::next(const Day10::Coord &previous, const Day10::Coord ¤t) const { |
||||
auto [c1, c2] = neighbours(current); |
||||
if (previous == c1) |
||||
return c2; |
||||
if (previous == c2) |
||||
return c1; |
||||
exit(1); |
||||
} |
||||
|
||||
void Day10::Map::replaceStart(const vector<Coord> &loop) { |
||||
Coord prev = loop.back(); |
||||
Coord start = loop[0]; |
||||
Coord next = loop[1]; |
||||
|
||||
auto east = Coord({start.x + 1, start.y}); |
||||
auto west = Coord({start.x - 1, start.y}); |
||||
auto south = Coord({start.x, start.y + 1}); |
||||
auto north = Coord({start.x, start.y - 1}); |
||||
|
||||
Tile result; |
||||
for (size_t i = 2; i < 8; i++){ |
||||
bool found = false; |
||||
Tile tile = Tile(i); |
||||
switch (tile) { |
||||
case SOUTH_EAST: |
||||
found = (prev == east && next == south) || (prev == south && next == east); |
||||
break; |
||||
case SOUTH_WEST: |
||||
found = (prev == west && next == south) || (prev == south && next == west); |
||||
break; |
||||
case NORTH_EAST: |
||||
found = (prev == east && next == north) || (prev == north && next == east); |
||||
break; |
||||
case NORTH_WEST: |
||||
found = (prev == west && next == north) || (prev == north && next == west); |
||||
break; |
||||
case HORIZONTAL: |
||||
found = (prev == east && next == west) || (prev == west && next == east); |
||||
break; |
||||
case VERTICAL: |
||||
found = (prev == south && next == north) || (prev == north && next == south); |
||||
break; |
||||
default: |
||||
exit(1); |
||||
} |
||||
if (found) |
||||
result = tile; |
||||
} |
||||
|
||||
tiles[start.y][start.x] = result; |
||||
} |
||||
|
||||
pair<Day10::Coord, Day10::Coord> Day10::Map::neighbours(const Day10::Coord &c) const { |
||||
Coord c1 {}, c2 {}; |
||||
switch (at(c)) { |
||||
case SOUTH_EAST: |
||||
c1 = {c.x, c.y + 1}; |
||||
c2 = {c.x + 1, c.y}; |
||||
break; |
||||
case SOUTH_WEST: |
||||
c1 = {c.x, c.y + 1}; |
||||
c2 = {c.x - 1, c.y}; |
||||
break; |
||||
case NORTH_EAST: |
||||
c1 = {c.x, c.y - 1}; |
||||
c2 = {c.x + 1, c.y}; |
||||
break; |
||||
case NORTH_WEST: |
||||
c1 = {c.x, c.y - 1}; |
||||
c2 = {c.x - 1, c.y}; |
||||
break; |
||||
case HORIZONTAL: |
||||
c1 = {c.x - 1, c.y}; |
||||
c2 = {c.x + 1, c.y}; |
||||
break; |
||||
case VERTICAL: |
||||
c1 = {c.x, c.y - 1}; |
||||
c2 = {c.x, c.y + 1}; |
||||
break; |
||||
default: |
||||
exit(1); |
||||
} |
||||
return {c1, c2}; |
||||
} |
||||
|
||||
bool Day10::Coord::operator==(const Day10::Coord &other) const { |
||||
return x == other.x && y == other.y; |
||||
} |
Loading…
Reference in new issue