From 1e991c1f77e219f7f31df7e0b0830b7c90af9c6d Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Tue, 19 Dec 2023 18:39:46 +0100 Subject: [PATCH] Day 10 --- src/days/10/Day10.cpp | 222 +++++++++++++++++++++++++++++++++++++++++- src/days/10/Day10.h | 28 ++++++ 2 files changed, 247 insertions(+), 3 deletions(-) diff --git a/src/days/10/Day10.cpp b/src/days/10/Day10.cpp index 8801a58..d98794b 100644 --- a/src/days/10/Day10.cpp +++ b/src/days/10/Day10.cpp @@ -1,9 +1,225 @@ #include "Day10.h" Result Day10::Task1() { - return Day::Task1(); + Map map = parseMap(); + + Coord start = getStart(); + + vector>> 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 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(); -} \ No newline at end of file + Map map = parseMap(); + + Coord start = getStart(); + + vector>> 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 loop = {start}; + + while (map.at(current) != START) { + loop.push_back(current); + Coord next = map.next(previous, current); + previous = current; + current = next; + } + + vector> mask(map.tiles.size(), vector(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 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 &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::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; +} diff --git a/src/days/10/Day10.h b/src/days/10/Day10.h index a4713aa..2790d46 100644 --- a/src/days/10/Day10.h +++ b/src/days/10/Day10.h @@ -3,6 +3,34 @@ #include "../../Day.h" class Day10 : public Day { + + enum Tile {START = 0, GROUND, SOUTH_EAST, SOUTH_WEST, NORTH_EAST, NORTH_WEST, HORIZONTAL, VERTICAL}; + map charToTile = { + {'S', START}, + {'.', GROUND}, + {'F', SOUTH_EAST}, + {'7', SOUTH_WEST}, + {'L', NORTH_EAST}, + {'J', NORTH_WEST}, + {'-', HORIZONTAL}, + {'|', VERTICAL}, + }; + struct Coord { + size_t x; + size_t y; + bool operator ==(const Coord &other) const; + }; + struct Map { + vector> tiles; + Tile at(const Coord &c) const; + Coord next(const Coord& previous, const Coord ¤t) const; + pair neighbours(const Coord &c) const; + void replaceStart(const vector &loop); + }; + + Map parseMap() const; + Coord getStart() const; + protected: Result Task1() override;