parent
86120c01a1
commit
1e991c1f77
2 changed files with 247 additions and 3 deletions
@ -1,9 +1,225 @@ |
|||||||
#include "Day10.h" |
#include "Day10.h" |
||||||
|
|
||||||
Result Day10::Task1() { |
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() { |
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