aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

commit d3cff0510e46c60b6d93e0852729ffd359b39e3d
parent 98a6013504e955bc8ed91e5b70ad94069d493428
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sat, 21 Dec 2024 08:53:28 +0100

Day 21 2024

Diffstat:
A2024/21/Makefile | 11+++++++++++
A2024/21/day21a-debuggable.cpp | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2024/21/day21a.cpp | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2024/21/day21b.cpp | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2024/21/input | 5+++++
A2024/21/test | 5+++++
6 files changed, 351 insertions(+), 0 deletions(-)

diff --git a/2024/21/Makefile b/2024/21/Makefile @@ -0,0 +1,11 @@ +CC=g++ -std=c++20 -g -Wall + +a: + ${CC} -o a.out day21a.cpp + ./a.out + +b: + ${CC} -o b.out day21b.cpp + ./b.out + +.PHONY: a b diff --git a/2024/21/day21a-debuggable.cpp b/2024/21/day21a-debuggable.cpp @@ -0,0 +1,129 @@ +#include <algorithm> +#include <cstdint> +#include <iostream> +#include <limits> +#include <map> +#include <queue> +#include <ranges> +#include <set> +#include <sstream> +#include <string> +#include <string_view> +#include <vector> +using namespace std; + +map<char, pair<int, int>> m_num = { + {'7', {0,0}}, {'8', {0,1}}, {'9', {0,2}}, + {'4', {1,0}}, {'5', {1,1}}, {'6', {1,2}}, + {'1', {2,0}}, {'2', {2,1}}, {'3', {2,2}}, + {'x', {3,0}}, {'0', {3,1}}, {'A', {3,2}}, +}; + +map<char, pair<int, int>> m_dir = { + {'x', {0,0}}, {'^', {0,1}}, {'A', {0,2}}, + {'<', {1,0}}, {'v', {1,1}}, {'>', {1,2}}, +}; + +map<pair<int, int>, char> rev_num; +map<pair<int, int>, char> rev_dir; + +map<pair<char, char>, vector<string>> p; + +vector<pair<pair<int, int>, char>> directions = { + {{1,0}, 'v'}, {{-1,0}, '^'}, {{0,1}, '>'}, {{0,-1}, '<'} +}; + +int distance(int cx, int cy, int dx, int dy) { + return abs(cx-dx) + abs(cy-dy); +} + +vector<string> paths(char c, char d, + map<char, pair<int, int>>& m, map<pair<int, int>, char>& rev) { + if (p[make_pair(c, d)].size() != 0) return p[make_pair(c, d)]; + if (c == d) return {""}; + if (c == 'x') return {}; + + vector<string> v; + auto [cx, cy] = m[c]; + auto [dx, dy] = m[d]; + for (auto [dir, dirc] : directions) { + pair i = make_pair(cx+dir.first, cy+dir.second); + if (distance(cx, cy, dx, dy) < distance(i.first, i.second, dx, dy)) + continue; + auto next = paths(rev[i], d, m, rev); + for (auto n : next) + v.push_back(dirc+n); + } + + return p[make_pair(c, d)] = v; +} + +string pushes_human(char c, char d) { + auto p = paths(c, d, m_dir, rev_dir); + auto shortest = numeric_limits<size_t>::max(); + string ret; + for (auto path : p) { + if (path.size() + 1 < shortest) { + ret = path + 'A'; + shortest = path.size() + 1; + } + } + return ret; +} + +string pushes_dir1(char c, char d) { + auto p = paths(c, d, m_dir, rev_dir); + auto shortest = numeric_limits<size_t>::max(); + string ret; + for (auto path : p) { + path = 'A' + path + 'A'; + string pushes = ""; + for (unsigned i = 0; i < path.size()-1; i++) + pushes += pushes_human(path[i], path[i+1]); + if (pushes.size() < shortest) { + ret = pushes; + shortest = pushes.size(); + } + } + return ret; +} + +string pushes_numpad(char c, char d) { + auto p = paths(c, d, m_num, rev_num); + auto shortest = numeric_limits<size_t>::max(); + string ret; + for (auto path : p) { + path = 'A' + path + 'A'; + string pushes = ""; + for (unsigned i = 0; i < path.size()-1; i++) + pushes += pushes_dir1(path[i], path[i+1]); + if (pushes.size() < shortest) { + ret = pushes; + shortest = pushes.size(); + } + } + return ret; +} + +int64_t numeric(const string& code) { + return (code[0]-'0')*100 + (code[1]-'0')*10 + (code[2]-'0'); +} + +int main() { + for (auto [k, v] : m_num) rev_num[v] = k; + for (auto [k, v] : m_dir) rev_dir[v] = k; + + string line; + int64_t tot = 0; + while (getline(cin, line)) { + string ppp; + int64_t num = numeric(line); + line = 'A' + line; + for (unsigned i = 0; i < line.size()-1; i++) + ppp += pushes_numpad(line[i], line[i+1]); + cout << ppp << endl; + tot += ppp.size() * num; + } + cout << tot << endl; + return 0; +} diff --git a/2024/21/day21a.cpp b/2024/21/day21a.cpp @@ -0,0 +1,99 @@ +#include <algorithm> +#include <cstdint> +#include <iostream> +#include <limits> +#include <map> +#include <queue> +#include <ranges> +#include <set> +#include <sstream> +#include <string> +#include <string_view> +#include <vector> +using namespace std; + +map<char, pair<int, int>> m_num = { + {'7', {0,0}}, {'8', {0,1}}, {'9', {0,2}}, + {'4', {1,0}}, {'5', {1,1}}, {'6', {1,2}}, + {'1', {2,0}}, {'2', {2,1}}, {'3', {2,2}}, + {'x', {3,0}}, {'0', {3,1}}, {'A', {3,2}}, +}; + +map<char, pair<int, int>> m_dir = { + {'x', {0,0}}, {'^', {0,1}}, {'A', {0,2}}, + {'<', {1,0}}, {'v', {1,1}}, {'>', {1,2}}, +}; + +map<pair<int, int>, char> rev_num; +map<pair<int, int>, char> rev_dir; + +map<pair<char, char>, vector<string>> p; + +vector<pair<pair<int, int>, char>> directions = { + {{1,0}, 'v'}, {{-1,0}, '^'}, {{0,1}, '>'}, {{0,-1}, '<'} +}; + +int distance(int cx, int cy, int dx, int dy) { + return abs(cx-dx) + abs(cy-dy); +} + +vector<string> paths(char c, char d, + map<char, pair<int, int>>& m, map<pair<int, int>, char>& rev) { + if (p[make_pair(c, d)].size() != 0) return p[make_pair(c, d)]; + if (c == d) return {""}; + if (c == 'x') return {}; + + vector<string> v; + auto [cx, cy] = m[c]; + auto [dx, dy] = m[d]; + for (auto [dir, dirc] : directions) { + pair i = make_pair(cx+dir.first, cy+dir.second); + if (distance(cx, cy, dx, dy) < distance(i.first, i.second, dx, dy)) + continue; + auto next = paths(rev[i], d, m, rev); + for (auto n : next) + v.push_back(dirc+n); + } + + return p[make_pair(c, d)] = v; +} + +int64_t pushes(char c, char d, map<char, + pair<int, int>>& m, map<pair<int, int>, char>& r, int n) { + auto p = paths(c, d, m, r); + auto ret = numeric_limits<int64_t>::max(); + for (auto path : p) { + if (n == 0) { + ret = min(ret, (int64_t)path.size()+1); + } else { + path = 'A' + path + 'A'; + int64_t u = 0; + for (unsigned i = 0; i < path.size()-1; i++) + u += pushes(path[i], path[i+1], m_dir, rev_dir, n-1); + ret = min(ret, u); + } + } + return ret; +} + +int64_t numeric(const string& code) { + return (code[0]-'0')*100 + (code[1]-'0')*10 + (code[2]-'0'); +} + +int main() { + for (auto [k, v] : m_num) rev_num[v] = k; + for (auto [k, v] : m_dir) rev_dir[v] = k; + + string line; + int64_t tot = 0; + while (getline(cin, line)) { + int64_t comp = 0; + int64_t num = numeric(line); + line = 'A' + line; + for (unsigned i = 0; i < line.size()-1; i++) + comp += pushes(line[i], line[i+1], m_num, rev_num, 2); + tot += comp * num; + } + cout << tot << endl; + return 0; +} diff --git a/2024/21/day21b.cpp b/2024/21/day21b.cpp @@ -0,0 +1,102 @@ +#include <algorithm> +#include <cstdint> +#include <iostream> +#include <limits> +#include <map> +#include <queue> +#include <ranges> +#include <set> +#include <sstream> +#include <string> +#include <string_view> +#include <vector> +using namespace std; + +map<char, pair<int, int>> m_num = { + {'7', {0,0}}, {'8', {0,1}}, {'9', {0,2}}, + {'4', {1,0}}, {'5', {1,1}}, {'6', {1,2}}, + {'1', {2,0}}, {'2', {2,1}}, {'3', {2,2}}, + {'x', {3,0}}, {'0', {3,1}}, {'A', {3,2}}, +}; + +map<char, pair<int, int>> m_dir = { + {'x', {0,0}}, {'^', {0,1}}, {'A', {0,2}}, + {'<', {1,0}}, {'v', {1,1}}, {'>', {1,2}}, +}; + +map<pair<int, int>, char> rev_num; +map<pair<int, int>, char> rev_dir; + +map<pair<char, char>, vector<string>> p; + +vector<pair<pair<int, int>, char>> directions = { + {{1,0}, 'v'}, {{-1,0}, '^'}, {{0,1}, '>'}, {{0,-1}, '<'} +}; + +int distance(int cx, int cy, int dx, int dy) { + return abs(cx-dx) + abs(cy-dy); +} + +vector<string> paths(char c, char d, + map<char, pair<int, int>>& m, map<pair<int, int>, char>& rev) { + if (p[make_pair(c, d)].size() != 0) return p[make_pair(c, d)]; + if (c == d) return {""}; + if (c == 'x') return {}; + + vector<string> v; + auto [cx, cy] = m[c]; + auto [dx, dy] = m[d]; + for (auto [dir, dirc] : directions) { + pair i = make_pair(cx+dir.first, cy+dir.second); + if (distance(cx, cy, dx, dy) < distance(i.first, i.second, dx, dy)) + continue; + const auto next = paths(rev[i], d, m, rev); + for (auto n : next) + v.push_back(dirc+n); + } + + return p[make_pair(c, d)] = v; +} + +map<tuple<char, char, int>, int64_t> t; +int64_t pushes(char c, char d, + map<char, pair<int, int>>& m, map<pair<int, int>, char>& r, int n) { + if (t.count(make_tuple(c, d, n))) + return t[make_tuple(c, d, n)]; + const auto p = paths(c, d, m, r); + auto ret = numeric_limits<int64_t>::max(); + for (const auto& path : p) { + if (n == 0) { + ret = min(ret, (int64_t)path.size()+1); + } else { + string q = 'A' + path + 'A'; + int64_t u = 0; + for (unsigned i = 0; i < q.size()-1; i++) + u += pushes(q[i], q[i+1], m_dir, rev_dir, n-1); + ret = min(ret, u); + } + } + return t[make_tuple(c, d, n)] = ret; +} + +int64_t numeric(const string& code) { + return (code[0]-'0')*100 + (code[1]-'0')*10 + (code[2]-'0'); +} + +int main() { + for (auto [k, v] : m_num) rev_num[v] = k; + for (auto [k, v] : m_dir) rev_dir[v] = k; + + string line; + int64_t tot = 0; + while (getline(cin, line)) { + int64_t comp = 0; + int64_t num = numeric(line); + line = 'A' + line; + for (unsigned i = 0; i < line.size()-1; i++) + comp += pushes(line[i], line[i+1], m_num, rev_num, 25); + tot += comp * num; + } + cout << tot << endl; + return 0; +} diff --git a/2024/21/input b/2024/21/input @@ -0,0 +1,5 @@ +340A +586A +839A +413A +968A diff --git a/2024/21/test b/2024/21/test @@ -0,0 +1,5 @@ +029A +980A +179A +456A +379A