day 12
This commit is contained in:
parent
82f0905457
commit
35af3ff7a5
1
12/.gitignore
vendored
Normal file
1
12/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
day12
|
9
12/README.md
Normal file
9
12/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# [Day 12](https://adventofcode.com/2022/day/12)
|
||||
:gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift::gift:
|
||||
|
||||
Today's language: **C++**
|
||||
|
||||
```shell
|
||||
g++ -std=c++20 day12.cpp -o day12
|
||||
./day12
|
||||
```
|
164
12/day12.cpp
Normal file
164
12/day12.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <unordered_set>
|
||||
#include <gz-util/container/queue.hpp>
|
||||
|
||||
|
||||
constexpr char UP = (1 << 1);
|
||||
constexpr char DOWN = (1 << 2);
|
||||
constexpr char LEFT = (1 << 3);
|
||||
constexpr char RIGHT = (1 << 4);
|
||||
|
||||
using ssize = std::string::size_type;
|
||||
|
||||
struct XY {
|
||||
ssize x;
|
||||
ssize y;
|
||||
bool operator==(const XY& other) const { return this->x == other.x && this->y == other.y; };
|
||||
struct Hash {
|
||||
size_t operator()(const XY& xy) const {
|
||||
return (std::hash<ssize>()(xy.x) << 1) ^ (std::hash<ssize>()(xy.y));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class String2D {
|
||||
public:
|
||||
String2D(ssize w, std::string::size_type h, char c) : s((w + 1) * h, c), width(w), height(h) {
|
||||
for (ssize i = width; i < s.size(); i += width + 1) {
|
||||
s.at(i) = '\n';
|
||||
}
|
||||
}
|
||||
String2D(std::string&& str) : s(std::move(str)) {
|
||||
width = s.find('\n');
|
||||
height = s.size() / (width + 1);
|
||||
}
|
||||
const char& at(ssize x, std::string::size_type y) const {
|
||||
assert(x < width);
|
||||
assert(y < height);
|
||||
return s.at(x + y * (width + 1));
|
||||
}
|
||||
char& at(ssize x, std::string::size_type y) {
|
||||
assert(x < width);
|
||||
assert(y < height);
|
||||
return s.at(x + y * (width + 1));
|
||||
}
|
||||
void set(ssize x, std::string::size_type y, char c) {
|
||||
assert(x < width);
|
||||
assert(y < height);
|
||||
s.at(x + y * (width + 1)) = c;
|
||||
}
|
||||
XY find(char c) {
|
||||
ssize i = s.find(c);
|
||||
if (i != std::string::npos) { return indexToPos(i); }
|
||||
return XY{std::string::npos, std::string::npos};
|
||||
}
|
||||
XY indexToPos(ssize i) { return XY{.x = i % (width + 1), .y = i / (width + 1) }; }
|
||||
inline const ssize& getWidth() const { return width; }
|
||||
inline const ssize& getHeight() const { return height; }
|
||||
const std::string& getString() const { return s; }
|
||||
private:
|
||||
std::string s;
|
||||
ssize width, height;
|
||||
};
|
||||
|
||||
bool isReachable(char c) {
|
||||
return c <= 1;
|
||||
}
|
||||
|
||||
String2D createNodes(const String2D& hill) {
|
||||
String2D dirs(hill.getWidth(), hill.getHeight(), 0);
|
||||
for (size_t x = 0; x < hill.getWidth(); x++) {
|
||||
for (size_t y = 0; y < hill.getHeight(); y++) {
|
||||
char c = hill.at(x, y);
|
||||
if (x > 0) {
|
||||
if (isReachable(hill.at(x - 1, y) - c)) { dirs.at(x, y) |= LEFT; }
|
||||
}
|
||||
if (x < hill.getWidth() - 1) {
|
||||
if (isReachable(hill.at(x + 1, y) - c)) { dirs.at(x, y) |= RIGHT; }
|
||||
}
|
||||
if (y > 0) {
|
||||
if (isReachable(hill.at(x, y - 1) - c)) { dirs.at(x, y) |= UP; }
|
||||
}
|
||||
if (y < hill.getHeight() - 1) {
|
||||
if (isReachable(hill.at(x, y + 1) - c)) { dirs.at(x, y) |= DOWN; }
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
ssize shortestPath(const String2D& nodes, XY start, XY end) {
|
||||
gz::Queue<XY> waitlists[2];
|
||||
unsigned currentWaitlist = 0;
|
||||
unsigned otherWaitlist = 1;
|
||||
std::unordered_set<XY, XY::Hash> processed;
|
||||
ssize length = 0;
|
||||
auto queue = [&processed](gz::Queue<XY>& q, XY xy) {
|
||||
if (!processed.contains(xy)) {
|
||||
processed.insert(xy);
|
||||
q.push_back(xy);
|
||||
}
|
||||
};
|
||||
queue(waitlists[currentWaitlist], start);
|
||||
while (waitlists[0].hasElement() || waitlists[1].hasElement()) {
|
||||
while (waitlists[currentWaitlist].hasElement()) {
|
||||
XY& pos = waitlists[currentWaitlist].getRef();
|
||||
if (pos == end) { goto done; }
|
||||
char c = nodes.at(pos.x, pos.y);
|
||||
if (c & LEFT) { queue(waitlists[otherWaitlist], XY{pos.x - 1, pos.y}); }
|
||||
if (c & RIGHT) { queue(waitlists[otherWaitlist], XY{pos.x + 1, pos.y}); }
|
||||
if (c & UP) { queue(waitlists[otherWaitlist], XY{pos.x, pos.y - 1}); }
|
||||
if (c & DOWN) { queue(waitlists[otherWaitlist], XY{pos.x, pos.y + 1}); }
|
||||
}
|
||||
otherWaitlist = currentWaitlist;
|
||||
currentWaitlist = ++currentWaitlist % 2;
|
||||
length++;
|
||||
}
|
||||
std::cerr << "Could not find path\n";
|
||||
return std::string::npos;
|
||||
done:
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
const char* filename;
|
||||
if (argc != 2) { filename = "hill.txt"; }
|
||||
else { filename = argv[1]; }
|
||||
|
||||
std::ifstream file(filename);
|
||||
if (!file.is_open()) {
|
||||
std::cout << "Could not open file\n";
|
||||
return 1;
|
||||
}
|
||||
std::ostringstream ss;
|
||||
ss << file.rdbuf();
|
||||
file.close();
|
||||
String2D hill2D(ss.str());
|
||||
XY start = hill2D.find('S');
|
||||
XY end = hill2D.find('E');
|
||||
hill2D.at(start.x, start.y) = 'a';
|
||||
hill2D.at(end.x, end.y) = 'z';
|
||||
/* printf("Start: (%lu, %lu), End: (%lu, %lu)\n", start.x, start.y, end.x, end.y); */
|
||||
auto nodes = createNodes(hill2D);
|
||||
ssize length = shortestPath(nodes, start, end);
|
||||
std::cout << "Shortest path has length: " << length << "\n";
|
||||
|
||||
// Task 2
|
||||
ssize minLength = std::string::npos;
|
||||
ssize startAt = 0;
|
||||
ssize aIndex = hill2D.getString().find('a', startAt);
|
||||
while (aIndex != std::string::npos) {
|
||||
XY pos = hill2D.indexToPos(aIndex);
|
||||
ssize length_ = shortestPath(nodes, hill2D.indexToPos(aIndex), end);
|
||||
/* printf("Path from (%lu, %lu) to end has length: %lu\n", pos.x, pos.y, length_); */
|
||||
if (length_ < minLength) { minLength = length_; }
|
||||
startAt = aIndex + 1;
|
||||
aIndex = hill2D.getString().find('a', startAt);
|
||||
}
|
||||
printf("Shortest path from any a has length %lu\n", minLength);
|
||||
}
|
41
12/hill.txt
Normal file
41
12/hill.txt
Normal file
@ -0,0 +1,41 @@
|
||||
abccccaaaaaaacccaaaaaaaccccccccccccccccccccccccccccccccccaaaa
|
||||
abcccccaaaaaacccaaaaaaaaaaccccccccccccccccccccccccccccccaaaaa
|
||||
abccaaaaaaaaccaaaaaaaaaaaaaccccccccccccccccccccccccccccaaaaaa
|
||||
abccaaaaaaaaaaaaaaaaaaaaaaacccccccccaaaccccacccccccccccaaacaa
|
||||
abaccaaaaaaaaaaaaaaaaaacacacccccccccaaacccaaaccccccccccccccaa
|
||||
abaccccaaaaaaaaaaaaaaaacccccccccccccaaaaaaaaaccccccccccccccaa
|
||||
abaccccaacccccccccaaaaaacccccccccccccaaaaaaaacccccccccccccccc
|
||||
abcccccaaaacccccccaaaaaaccccccccijjjjjjaaaaaccccccaaccaaccccc
|
||||
abccccccaaaaacccccaaaacccccccciiijjjjjjjjjkkkkkkccaaaaaaccccc
|
||||
abcccccaaaaacccccccccccccccccciiiirrrjjjjjkkkkkkkkaaaaaaccccc
|
||||
abcccccaaaaaccccccccccccccccciiiirrrrrrjjjkkkkkkkkkaaaaaccccc
|
||||
abaaccacaaaaacccccccccccccccciiiqrrrrrrrrrrssssskkkkaaaaacccc
|
||||
abaaaaacaaccccccccccccccccccciiiqqrtuurrrrrsssssskklaaaaacccc
|
||||
abaaaaacccccccccccaaccccccccciiqqqttuuuurrssusssslllaaccccccc
|
||||
abaaaaaccccccccaaaaccccccccciiiqqqttuuuuuuuuuuusslllaaccccccc
|
||||
abaaaaaacccccccaaaaaaccccccciiiqqqttxxxuuuuuuuusslllccccccccc
|
||||
abaaaaaaccccaaccaaaaacccccchhiiqqtttxxxxuyyyyvvsslllccccccccc
|
||||
abaaacacccccaacaaaaaccccccchhhqqqqttxxxxxyyyyvvsslllccccccccc
|
||||
abaaacccccccaaaaaaaacccccchhhqqqqtttxxxxxyyyvvssqlllccccccccc
|
||||
abacccccaaaaaaaaaaccaaacchhhpqqqtttxxxxxyyyyvvqqqlllccccccccc
|
||||
SbaaacaaaaaaaaaaaacaaaaahhhhppttttxxEzzzzyyvvvqqqqlllcccccccc
|
||||
abaaaaaaacaaaaaacccaaaaahhhppptttxxxxxyyyyyyyvvqqqlllcccccccc
|
||||
abaaaaaaccaaaaaaaccaaaaahhhppptttxxxxywyyyyyyvvvqqqmmcccccccc
|
||||
abaaaaaaacaaaaaaacccaaaahhhpppsssxxwwwyyyyyyvvvvqqqmmmccccccc
|
||||
abaaaaaaaaaaaaaaacccaacahhhpppssssssswyyywwvvvvvqqqmmmccccccc
|
||||
abaaaaaaaacacaaaacccccccgggppppsssssswwywwwwvvvqqqqmmmccccccc
|
||||
abcaaacaaaccccaaaccccccccgggppppppssswwwwwrrrrrqqqmmmmccccccc
|
||||
abcaaacccccccccccccccccccgggggpppoosswwwwwrrrrrqqmmmmddcccccc
|
||||
abccaacccccccccccccccccccccgggggoooosswwwrrrnnnmmmmmddddccccc
|
||||
abccccccccccccccccccccccccccgggggooossrrrrrnnnnnmmmddddaccccc
|
||||
abaccccaacccccccccccccccccccccgggfoossrrrrnnnnndddddddaaacccc
|
||||
abaccaaaaaaccccccccccccccccccccgffooorrrrnnnneeddddddaaaacccc
|
||||
abaccaaaaaacccccccccccccccccccccfffooooonnnneeeddddaaaacccccc
|
||||
abacccaaaaaccccccccaaccaaaccccccffffoooonnneeeeccaaaaaacccccc
|
||||
abcccaaaaacccccccccaaccaaaaccccccffffoooneeeeeaccccccaacccccc
|
||||
abaccaaaaaccccccccaaaacaaaaccccccafffffeeeeeaaacccccccccccccc
|
||||
abacccccccccccccccaaaacaaacccccccccffffeeeecccccccccccccccaac
|
||||
abaaaacccccccaaaaaaaaaaaaaacccccccccfffeeeccccccccccccccccaaa
|
||||
abaaaacccccccaaaaaaaaaaaaaaccccccccccccaacccccccccccccccccaaa
|
||||
abaacccccccccaaaaaaaaaaaaaaccccccccccccaacccccccccccccccaaaaa
|
||||
abaaaccccccccccaaaaaaaaccccccccccccccccccccccccccccccccaaaaaa
|
@ -23,7 +23,7 @@ Also, check out the repositories of my friends who do stuff in go, Visual Basic,
|
||||
- **Assembly, x86-64**: day 4
|
||||
- **Bash**: day 1, 7
|
||||
- **C**: day 3, 4
|
||||
- **C++**: day 2, 8, 14
|
||||
- **C++**: day 2, 8, 12, 14
|
||||
- **HolyC:** day 13
|
||||
- **Java**: day 10
|
||||
- **Javascript**: day 6
|
||||
|
Loading…
Reference in New Issue
Block a user