Compare commits
2 commits
1f992486fd
...
8b47a9d0f8
Author | SHA1 | Date | |
---|---|---|---|
8b47a9d0f8 | |||
456cf1ef3f |
71
2024/16/main-1.cpp
Normal file
71
2024/16/main-1.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include <bits/stdc++.h>
|
||||
#include "../../include/aoc.hpp"
|
||||
using namespace std;
|
||||
|
||||
unordered_map<Coord<int>, unordered_map<int, int>> m;
|
||||
|
||||
inline Coord<int> posdir(int p) {
|
||||
switch (p) {
|
||||
case 0:
|
||||
return {0, 1};
|
||||
case 1:
|
||||
return {1, 0};
|
||||
case 2:
|
||||
return {0, -1};
|
||||
case 3:
|
||||
return {-1, 0};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void rec(Coord<int> pos, int dir, int score) {
|
||||
if (!m.contains(pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &mp = m[pos];
|
||||
if (mp.contains(dir) && mp[dir] <= score) {
|
||||
return;
|
||||
}
|
||||
|
||||
mp[dir] = score;
|
||||
rec(pos + posdir(dir), dir, score + 1);
|
||||
rec(pos, (dir + 1) & 3, score + 1000);
|
||||
rec(pos, (dir - 1) & 3, score + 1000);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ios::sync_with_stdio(0);
|
||||
cin.tie(0);
|
||||
|
||||
Coord<int> pos, s, e;
|
||||
string line;
|
||||
while (getline(cin, line) && !line.empty()) {
|
||||
for (pos.y = 0; pos.y < line.size(); pos.y++) {
|
||||
switch (line[pos.y]) {
|
||||
case '#':
|
||||
continue;
|
||||
case 'S':
|
||||
s = pos;
|
||||
break;
|
||||
case 'E':
|
||||
e = pos;
|
||||
break;
|
||||
}
|
||||
m[pos];
|
||||
}
|
||||
pos.x++;
|
||||
}
|
||||
|
||||
rec(s, 0, 0);
|
||||
|
||||
int minscore = -1;
|
||||
for (auto [dir, score] : m[e]) {
|
||||
if (minscore == -1 || score < minscore) {
|
||||
minscore = score;
|
||||
}
|
||||
}
|
||||
|
||||
cout << minscore << '\n';
|
||||
}
|
111
2024/16/main-2.cpp
Normal file
111
2024/16/main-2.cpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
#include <bits/stdc++.h>
|
||||
#include "../../include/aoc.hpp"
|
||||
using namespace std;
|
||||
|
||||
unordered_map<Coord<int>, unordered_map<int, pair<int, set<int>>>> m;
|
||||
|
||||
inline Coord<int> posdir(int p) {
|
||||
switch (p) {
|
||||
case 0:
|
||||
return {0, 1};
|
||||
case 1:
|
||||
return {1, 0};
|
||||
case 2:
|
||||
return {0, -1};
|
||||
case 3:
|
||||
return {-1, 0};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void rec(Coord<int> pos, int dir, int score, int follow) {
|
||||
if (!m.contains(pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &mp = m[pos];
|
||||
|
||||
if (mp.contains(dir)) {
|
||||
auto &[s, f] = mp[dir];
|
||||
if (s < score) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s > score) {
|
||||
f.clear();
|
||||
}
|
||||
f.insert(follow);
|
||||
if (s == score) {
|
||||
return;
|
||||
}
|
||||
|
||||
s = score;
|
||||
} else {
|
||||
mp[dir] = {score, {follow}};
|
||||
}
|
||||
|
||||
mp[dir].second.insert(follow);
|
||||
|
||||
rec(pos + posdir(dir), dir, score + 1, dir);
|
||||
rec(pos, (dir + 1) & 3, score + 1000, follow);
|
||||
rec(pos, (dir - 1) & 3, score + 1000, follow);
|
||||
}
|
||||
|
||||
void rec2(unordered_set<Coord<int>> &mm, Coord<int> pos, int dir) {
|
||||
mm.insert(pos);
|
||||
auto &[s, f] = m[pos][dir];
|
||||
for (auto follow : f) {
|
||||
if (follow == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rec2(mm, pos + posdir((follow + 2) & 3), follow);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
ios::sync_with_stdio(0);
|
||||
cin.tie(0);
|
||||
|
||||
Coord<int> pos, s, e;
|
||||
string line;
|
||||
while (getline(cin, line) && !line.empty()) {
|
||||
for (pos.y = 0; pos.y < line.size(); pos.y++) {
|
||||
switch (line[pos.y]) {
|
||||
case '#':
|
||||
continue;
|
||||
case 'S':
|
||||
s = pos;
|
||||
break;
|
||||
case 'E':
|
||||
e = pos;
|
||||
break;
|
||||
}
|
||||
m[pos];
|
||||
}
|
||||
pos.x++;
|
||||
}
|
||||
|
||||
rec(s, 0, 0, -1);
|
||||
|
||||
int minscore = -1;
|
||||
vector<int> dirs;
|
||||
for (auto &[dir, sf] : m[e]) {
|
||||
auto &[s, f] = sf;
|
||||
if (minscore == -1 || s < minscore) {
|
||||
minscore = s;
|
||||
dirs.clear();
|
||||
} else if (s > minscore) {
|
||||
continue;
|
||||
}
|
||||
dirs.push_back(dir);
|
||||
}
|
||||
|
||||
unordered_set<Coord<int>> mm;
|
||||
for (auto dir : dirs) {
|
||||
rec2(mm, e, dir);
|
||||
}
|
||||
|
||||
cout << mm.size() << '\n';
|
||||
}
|
107
include/aoc.hpp
Normal file
107
include/aoc.hpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef long long ll;
|
||||
typedef unsigned long long ull;
|
||||
|
||||
template <typename T> struct Coord {
|
||||
T x, y;
|
||||
|
||||
Coord() : Coord(0, 0) {}
|
||||
|
||||
Coord(const T x, const T y) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
Coord<T> operator-() { return {-this->x, -this->y}; }
|
||||
|
||||
Coord<T> &operator+=(const Coord<T> &other) {
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Coord<T> &operator-=(const Coord<T> &other) {
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Coord<T> &operator*=(const T other) {
|
||||
x *= other;
|
||||
y *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Coord<T> &operator/=(const T other) {
|
||||
x /= other;
|
||||
y /= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<Coord<T>> nearby(const Coord<T> &cMin, const Coord<T> &cMax) {
|
||||
std::vector<Coord<T>> ret;
|
||||
const T xMin = std::max(this->x - 1, cMin.x);
|
||||
const T xMax = std::min(this->x + 1, cMax.x);
|
||||
const T yMin = std::max(this->y - 1, cMin.y);
|
||||
const T yMax = std::min(this->y + 1, cMax.y);
|
||||
for (T x = xMin; x <= xMax; x++) {
|
||||
for (T y = yMin; y <= yMax; y++) {
|
||||
Coord<T> xy(x, y);
|
||||
if (*this != xy) {
|
||||
ret.push_back(xy);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Coord<T>> nearby(const Coord<T> &cMax) {
|
||||
return this->nearby(Coord<T>(), cMax);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Coord<T> operator+(const Coord<T> &lhs, const Coord<T> &rhs) {
|
||||
Coord<T> result = lhs;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Coord<T> operator-(const Coord<T> &lhs, const Coord<T> &rhs) {
|
||||
Coord<T> result = lhs;
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> Coord<T> operator*(const Coord<T> &lhs, const T rhs) {
|
||||
Coord<T> result = lhs;
|
||||
result *= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> Coord<T> operator/(const Coord<T> &lhs, const T rhs) {
|
||||
Coord<T> result = lhs;
|
||||
result /= rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(const Coord<T> &lhs, const Coord<T> &rhs) {
|
||||
return lhs.x == rhs.x && lhs.y == rhs.y;
|
||||
}
|
||||
|
||||
template <> struct std::hash<Coord<int>> {
|
||||
std::size_t operator()(const Coord<int> &c) const noexcept {
|
||||
return (c.x << (sizeof(std::size_t) / 2)) - c.x + c.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct std::hash<Coord<ull>> {
|
||||
std::size_t operator()(const Coord<ull> &c) const noexcept {
|
||||
return (c.x << (sizeof(std::size_t) / 2)) - c.x + c.y;
|
||||
}
|
||||
};
|
Loading…
Reference in a new issue