From 923918a20efb15c9314bf5c621fe8744e3377a58 Mon Sep 17 00:00:00 2001 From: jacopograndi Date: Thu, 24 Feb 2022 09:53:42 +0100 Subject: day23 --- 2021/day23/day23 | Bin 0 -> 354192 bytes 2021/day23/day23.cpp | 547 +++++++++++++++++++++++++++++++++++++++++++++ 2021/day23/day23_input.txt | 5 + 2021/day23/makefile | 2 + 2021/day23/test0.txt | 5 + 2021/day23/test1.txt | 5 + 2021/day23/test2.txt | 5 + 7 files changed, 569 insertions(+) create mode 100755 2021/day23/day23 create mode 100644 2021/day23/day23.cpp create mode 100644 2021/day23/day23_input.txt create mode 100644 2021/day23/makefile create mode 100644 2021/day23/test0.txt create mode 100644 2021/day23/test1.txt create mode 100644 2021/day23/test2.txt (limited to '2021') diff --git a/2021/day23/day23 b/2021/day23/day23 new file mode 100755 index 0000000..a19ddb7 Binary files /dev/null and b/2021/day23/day23 differ diff --git a/2021/day23/day23.cpp b/2021/day23/day23.cpp new file mode 100644 index 0000000..a07537d --- /dev/null +++ b/2021/day23/day23.cpp @@ -0,0 +1,547 @@ +#include +#include +#include +#include +#include +#include +#include + + +struct Game { + std::map> stars; + std::set single_cost; + std::vector cost; + std::vector goal; +}; + +std::vector games { + { + { + { 0, { 1 } }, + { 1, { 0, 2, 7 } }, + { 2, { 1, 7, 9, 3 } }, + { 3, { 2, 9, 11, 4 } }, + { 4, { 3, 11, 13, 5 } }, + { 5, { 4, 13, 6 } }, + { 6, { 5 } }, + { 7, { 1, 2, 8 } }, + { 8, { 7 } }, + { 9, { 2, 3, 10 } }, + { 10, { 9 } }, + { 11, { 3, 4, 12 } }, + { 12, { 11 } }, + { 13, { 4, 5, 14 } }, + { 14, { 13 } }, + }, + { 0, 8, 10, 12, 14, 6 }, + { 1, 10, 100, 1000 }, + { 8, 10, 12, 14 }, + }, + { + { + { 0, { 1 } }, + { 1, { 0, 2, 7 } }, + { 2, { 1, 7, 11, 3 } }, + { 3, { 2, 15, 11, 4 } }, + { 4, { 3, 15, 19, 5 } }, + { 5, { 4, 19, 6 } }, + { 6, { 5 } }, + { 7, { 1, 2, 8 } }, + { 8, { 7, 9 } }, + { 9, { 8, 10 } }, + { 10, { 9 } }, + { 11, { 2, 3, 12 } }, + { 12, { 11, 13 } }, + { 13, { 12, 14 } }, + { 14, { 13 } }, + { 15, { 3, 4, 16 } }, + { 16, { 15, 17 } }, + { 17, { 16, 18 } }, + { 18, { 17 } }, + { 19, { 4, 5, 20 } }, + { 20, { 19, 21 } }, + { 21, { 22, 20 } }, + { 22, { 21 } }, + }, + { 0, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 6 }, + { 1, 10, 100, 1000 }, + { 10, 14, 18, 22 }, + } +}; + + +class State { + public: + State () { } + State (std::vector pos): pos(pos) { } + State (const State& o): pos(o.pos) { } + + std::vector pos; + + bool operator==(const State &s) const { return pos==s.pos; } + + void dumb_parse (std::string raw) { + auto newline = raw.find("\n"); + raw = raw.substr(newline+1); + newline = raw.find("\n"); + raw = raw.substr(newline+1); + + std::string chars; + chars += std::string{ raw[3] } + + std::string{ raw[5] } + + std::string{ raw[7] } + + std::string{ raw[9] }; + + newline = raw.find("\n"); + raw = raw.substr(newline+1); + + chars += std::string{ raw[3] } + + std::string{ raw[5] } + + std::string{ raw[7] } + + std::string{ raw[9] }; + + int a = 0, b = 0, c = 0, d = 0; + for (int i=0; i row0 { 20,16,12,8 }; + std::vector row1 { 17,13,21,9 }; + for (int i=0; i<4; i++) { + int a = (pos[i*2]-7) / 2; + int b = 1-(pos[i*2])%2; + big.pos[i*4] = pos[i*2]+a*2+b*2; + a = (pos[i*2+1]-7) / 2; + b = 1-(pos[i*2+1])%2; + big.pos[i*4+3] = pos[i*2+1]+a*2+b*2; + big.pos[i*4+1] = row0[i]; + big.pos[i*4+2] = row1[i]; + } + return big; + } + + std::string show () { + std::string rep { "(State: [" }; + for (int i=0; i>; +using AllPaths = std::map>>; + +int bitsum (int n) { + int sum = 0; + while (n > 0) { + sum += n % 2; + n /= 2; + } + return sum; +} + +Paths get_paths (int mask, int pos, int type, int size=0) { + std::vector> frontier { { pos, pos } }; + std::map visited; + while (frontier.size() > 0) { + std::pair n = frontier[0]; + frontier.erase(frontier.begin()); + if (!visited.contains(n.first)) { + visited.insert(n); + for (int s : games[size].stars[n.first]) { + if (((mask >> s) & 1) == 0) { + frontier.push_back(std::pair { s, n.first } ); + } + } + } + } + + Paths paths; + for (auto v : visited) { + int energy = 0; + int iter { v.first }; + while (iter != pos) { + energy += 1; + int prev = visited[iter]; + if (!games[size].single_cost.contains(iter) + && !games[size].single_cost.contains(prev)) + energy ++; + iter = visited[iter]; + } + + if (energy == 0) continue; + + int end = v.first; + int goal = games[size].goal[type]; + if (end == goal) + return Paths { std::pair { end, energy } } ; + + if (pos == goal) continue; + if (pos < 7 && end < 7) continue; + + if (end == goal-1 + && (((mask >> goal) & 1) == 0)) continue; + + if (size == 0) { + if (end >= 7 + && (end != goal-1 + && end != goal)) continue; + } + else if (size == 1) { + if (end == goal-2 + && (((mask >> (goal-1)) & 1) == 0)) continue; + if (end == goal-3 + && (((mask >> (goal-2)) & 1) == 0)) continue; + if (end >= 7 + && end != goal-3 + && end != goal-2 + && end != goal-1 + && end != goal) continue; + } + + paths.push_back(std::pair { end, energy } ); + } + return paths; +} + +AllPaths construct_all_paths (int size=0) { + AllPaths all; + int i=0; + int perms = 32768, pieces = 8, cells = 15; + if (size == 1) { + perms = 8388608; pieces = 16; cells = 23; + } + + for (int mask=0; mask &states, int size=0) +{ + std::multimap next; + int init = state.pos[i]; + int type = i/(2+size*2); + for (auto p : all[state.mask()][init][type]) { + int goal = games[size].goal[type]; + + if (size == 0) { + int other = (i%2==0 ? 1 : 0) + (i/2)*2; + if (init == goal-1) + if (state.pos[other] == goal) continue; + + if (p.first == goal-1) { + if (state.pos[other] == goal) { + State n { state }; + n.pos[i] = p.first; + + int e = p.second * games[size].cost[type]+energy; + bool found = false; + auto range = states.equal_range(e); + for (auto j = range.first; j != range.second; ++j) { + if (j->second == n) { found = true; break; } + } + if (!found) states.insert({ e, n }); + return; + } else continue; + } + } else { + if (goal-3 <= init && init <= goal-1) { + auto it = std::find(state.pos.begin(), state.pos.end(), + init+1); + int other = it-state.pos.begin(); + if (other/4 == type) continue; + } + if (goal-3 <= p.first && p.first <= goal-1) { + auto it = std::find(state.pos.begin(), state.pos.end(), + p.first+1); + int other = it-state.pos.begin(); + if (other/4 == type) { + State n { state }; + n.pos[i] = p.first; + states.insert( + { p.second * games[size].cost[type]+energy, n } + ); + return; + } else continue; + } + } + + State n { state }; + n.pos[i] = p.first; + int e = p.second * games[size].cost[type]+energy; + bool found = false; + auto range = states.equal_range(e); + for (auto j = range.first; j != range.second; ++j) { + if (j->second == n) { found = true; break; } + } + if (!found) states.insert({ e, n }); + } + for (auto n : next) { + states.insert(n); + } +} + +int search (AllPaths &all, State init) { + std::vector done; + std::multimap states { { 0, init } }; + + + int size = init.pos.size() == 8 ? 0 : 1; + + int j=0; + int threshold = 0; + while (states.size() > 0) { + auto it = states.upper_bound(-1); + int energy = (*it).first; + State s { (*it).second }; + states.erase(it); + + if (j%10000 == 0) + std::cout << states.size() << "\t" << energy << "\t" + << s.show() << std::endl; + j++; + + if (!s.done()) { + for (int i=0; i