#include #include #include #include #include #include #include #include #include #include #include #include #include #include template std::size_t dedup(Map const& replacements, std::string& molecule) { std::size_t steps = 0; for (auto const& kv : replacements) { if (kv.first != kv.second + kv.second) { continue; } std::size_t pos = std::string::npos; do { pos = molecule.find(kv.first); if (pos != std::string::npos) { molecule = molecule.substr(0, pos) + kv.second + molecule.substr(pos + kv.first.size()); ++steps; } } while (pos != std::string::npos); } return steps; } #if 0 std::size_t simple_find(std::unordered_map const &replacements, std::string &molecule) { std::size_t steps = 0; bool changed = true; while (!molecule.empty() && molecule != "e" && changed) { changed = false; for (auto const &kv : replacements) { std::size_t pos = 0; while (pos != std::string::npos) { pos = molecule.find(kv.first, pos); if (pos != std::string::npos) { auto nm = molecule.substr(0, pos) + kv.second + molecule.substr(pos + kv.first.size()); bool good = true; for (auto const &kv2 : replacements) { auto left = std::max(kv2.first.size() - 1, pos) + 1 - kv2.first.size(); if (nm.substr(left, kv2.first.size() * 2 + kv.second.size() - 2) .find(kv2.first) != std::string::npos) { good = false; break; } } if (good) { ++steps; // std::cout << "Step: " << steps << ": " << molecule << " => " << // nm // << "\n"; molecule = nm; changed = true; } ++pos; } } } } return steps; } std::size_t find_molecule(std::unordered_map const &replacements, std::string const &m) { std::string molecule = m; std::size_t steps = 0; steps += dedup(replacements, molecule); steps += simple_find(replacements, molecule); std::unordered_map current_molecules = { {molecule, steps}}; while (!current_molecules.empty() && current_molecules.find("e") == current_molecules.end()) { std::unordered_map new_molecules; std::size_t mi = 0; for (auto const &m : current_molecules) { ++mi; std::string molecule = m.first; std::size_t steps = m.second; ++steps; for (auto const &kv : replacements) { std::size_t pos = 0; while (pos != std::string::npos) { pos = molecule.find(kv.first, pos); if (pos != std::string::npos) { bool good = false; auto nm = molecule.substr(0, pos) + kv.second + molecule.substr(pos + kv.first.size()); for (auto const &kv2 : replacements) { auto left = std::max(kv2.first.size(), pos) - kv2.first.size(); if (nm.substr(left, kv2.first.size() * 2 + kv.second.size()) .find(kv2.first) != std::string::npos) { good = true; break; } } if (good) { auto ns = steps; ns += dedup(replacements, nm); ns += simple_find(replacements, nm); std::cout << '\r' << steps << ": " << mi << " " << kv.first << " => " << kv.second; //<< " ==> " // << nm << "\n"; auto [it, success] = new_molecules.insert({nm, ns}); if (!success) { it->second = std::min(it->second, ns); } } ++pos; } } } } current_molecules = std::move(new_molecules); std::cout << "\nStep " << 1000000 << " : " << current_molecules.size() << " modulecules.\n" << std::flush; } std::cout << "\n"; return current_molecules.find("e")->second; } #endif template bool is_good_replacement(Map const& replacements, std::string const& nm, std::size_t pos, std::size_t replace_len) { for (auto const& kv : replacements) { auto left = std::max(kv.first.size(), pos) - kv.first.size(); if (nm.substr(left, kv.first.size() * 2 + replace_len).find(kv.first) != std::string::npos) { return true; } } return false; } template std::size_t find_molecule(Map& replacements, std::string const& molecule) { std::random_device rd; std::mt19937 g(rd()); while (true) { std::string m = molecule; bool changed = true; std::shuffle(replacements.begin(), replacements.end(), g); std::size_t steps = 0; do { changed = false; for (auto const& kv : replacements) { auto pos = m.find(kv.first); if (pos != std::string::npos) { m = m.substr(0, pos) + kv.second + m.substr(pos + kv.first.length()); std::cout << "\r" << steps << " "; ++steps; changed = true; if (m == "e") { std::cout << '\n'; return steps; } } } std::cout << '\n'; } while (changed); } } int main(int argc, char** argv) { std::vector> replacements; bool collecting_replacements = true; std::string line; while (std::getline(std::cin, line)) { if (line.empty()) { collecting_replacements = false; } else if (collecting_replacements) { auto sep = line.find(" => "); replacements.push_back({line.substr(sep + 4), line.substr(0, sep)}); } else { std::cout << line << "\n"; auto time = find_molecule(replacements, line); std::cout << "Solution: " << time << "\n"; } } return 0; }