#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