| 
						
						
							
								
							
						
						
					 | 
					@ -2,10 +2,10 @@ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <queue> | 
					 | 
					 | 
					#include <queue> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <absl/container/btree_map.h> | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <absl/container/btree_set.h> | 
					 | 
					 | 
					#include <absl/container/btree_set.h> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <absl/container/flat_hash_map.h> | 
					 | 
					 | 
					#include <absl/container/flat_hash_map.h> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <absl/container/node_hash_map.h> | 
					 | 
					 | 
					#include <absl/container/node_hash_map.h> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#include <core/core.h> | 
					 | 
					 | 
					#include <core/core.h> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					static KLSK_INLINE uint32_t type_id(const int n, const int n_2x1, const int n_1x1) { | 
					 | 
					 | 
					static KLSK_INLINE uint32_t type_id(const int n, const int n_2x1, const int n_1x1) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -31,78 +31,126 @@ std::vector<uint64_t> klotski::cases::group_extend_from_seed(uint64_t raw_code) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    auto max_size = GroupUnion::create(raw_code_to_type_id(raw_code))->max_group_size(); | 
					 | 
					 | 
					    auto max_size = GroupUnion::create(raw_code_to_type_id(raw_code))->max_group_size(); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // std::queue<uint64_t> cache({raw_code});
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    uint64_t offset = 0; | 
					 | 
					 | 
					    uint64_t offset = 0; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    std::vector<uint64_t> results; | 
					 | 
					 | 
					    std::vector<uint64_t> results; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    results.reserve(max_size); | 
					 | 
					 | 
					    results.reserve(max_size); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    results.emplace_back(raw_code); | 
					 | 
					 | 
					    results.emplace_back(raw_code); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // uint64_t offset = 0;
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // std::vector<std::pair<uint64_t, uint64_t>> results;
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // results.reserve(max_size);
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // results.emplace_back(raw_code, 0);
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    absl::flat_hash_map<uint64_t, uint64_t> cases; // <code, mask>
 | 
					 | 
					 | 
					    absl::flat_hash_map<uint64_t, uint64_t> cases; // <code, mask>
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // absl::node_hash_map<uint64_t, uint64_t> cases; // <code, mask>
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // std::unordered_map<uint64_t, uint64_t> cases; // <code, mask>
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // std::map<uint64_t, uint64_t> cases; // <code, mask>
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // absl::btree_map<uint64_t, uint64_t> cases; // <code, mask>
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    cases.reserve(max_size); | 
					 | 
					 | 
					    cases.reserve(max_size); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    cases.emplace(raw_code, 0); // without mask
 | 
					 | 
					 | 
					    cases.emplace(raw_code, 0); // without mask
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // std::cout << max_size << std::endl;
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    auto core = klotski::core::Core( | 
					 | 
					 | 
					    auto core = klotski::core::Core( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        [&results, &cases](auto code, auto mask) { // callback function
 | 
					 | 
					 | 
					        [&results, &cases](auto code, auto mask) { // callback function
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            auto current = cases.find(code); | 
					 | 
					 | 
					            auto current = cases.find(code); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            if (current != cases.end()) { | 
					 | 
					 | 
					            if (current != cases.end()) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                current->second |= mask; // update mask
 | 
					 | 
					 | 
					                current->second |= mask; // update mask
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                // results[current->second].second |= mask; // update mask
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                return; | 
					 | 
					 | 
					                return; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            } | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            cases.emplace(code, mask); | 
					 | 
					 | 
					            cases.emplace(code, mask); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            // cases.emplace(code, results.size());
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            // cache.emplace(code);
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            results.emplace_back(code); | 
					 | 
					 | 
					            results.emplace_back(code); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            // cache.emplace(code, 0);
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            // results.emplace_back(code, 0);
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        } | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    ); | 
					 | 
					 | 
					    ); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    while (offset != results.size()) { | 
					 | 
					 | 
					    while (offset != results.size()) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        auto tmp = results[offset]; | 
					 | 
					 | 
					        auto tmp = results[offset]; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        core.next_cases(tmp, cases.find(tmp)->second); | 
					 | 
					 | 
					        core.next_cases(tmp, cases.find(tmp)->second); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        // core.next_cases(tmp, 0);
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        // core.next_cases(tmp.first, tmp.second);
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        ++offset; | 
					 | 
					 | 
					        ++offset; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return results; | 
					 | 
					 | 
					    return results; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // return {};
 | 
					 | 
					 | 
					} | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					template<int N> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					static std::vector<uint32_t> demo(int n_10, int n_11) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // while (!cache.empty()) { // until BFS without elements
 | 
					 | 
					 | 
					    constexpr auto num = 16 - N; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    //     core.next_cases(cache.front(), cases.find(cache.front())->second);
 | 
					 | 
					 | 
					    constexpr auto offset = (16 - num) << 1; // offset of low bits
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    //     cache.pop(); // case dequeue
 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // }
 | 
					 | 
					 | 
					    int n_00 = 16 - N * 2 - n_11; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    int n_01 = N - n_10; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // std::vector<uint64_t> result;
 | 
					 | 
					 | 
					    std::array<int, num> series {}; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // result.reserve(cases.size());
 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // for (auto &&tmp : cases) { // export group cases
 | 
					 | 
					 | 
					    // for (int k = 0; k < n_00; ++k) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    //     result.emplace_back(tmp.first);
 | 
					 | 
					 | 
					    //     series[k] = 0b00;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // }
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // for (int k = n_00; k < n_00 + n_01; ++k) {
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     series[k] = 0b01;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // }
 | 
					 | 
					 | 
					    // }
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // return result;
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // std::vector<uint64_t> result;
 | 
					 | 
					 | 
					    auto kk = std::fill_n(series.begin() + n_00, n_01, 0b01); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // result.reserve(results.size());
 | 
					 | 
					 | 
					    auto pp = std::fill_n(kk, n_10, 0b10); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // for (auto [code, _] : results) {
 | 
					 | 
					 | 
					    std::fill_n(pp, n_11, 0b11); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    //     result.emplace_back(code);
 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // for (auto x : series) {
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     std::cout << x << " ";
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    // }
 | 
					 | 
					 | 
					    // }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    // return result;
 | 
					 | 
					 | 
					    // std::cout << std::endl;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    std::vector<uint32_t> ranges; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    do { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        uint32_t range = 0; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        for (const auto x : series) // store every 2-bit
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            (range <<= 2) |= x; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        ranges.emplace_back(range << offset); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } while (std::ranges::next_permutation(series).found); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    return ranges; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					std::vector<uint32_t> klotski::cases::spawn_ranges(int n_00, int n_01, int n_10, int n_11) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    auto n = n_01 + n_10; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    switch (n) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 0: return demo<0>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 1: return demo<1>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 2: return demo<2>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 3: return demo<3>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 4: return demo<4>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 5: return demo<5>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 6: return demo<6>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 7: return demo<7>(n_10, n_11); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        default: return {}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // return demo<5>(n_10, n_11);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // auto num = n_00 + n_01 + n_10 + n_11;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // auto offset = (16 - num) << 1; // offset of low bits
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // std::vector<int> series;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // series.reserve(num);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // series.insert(series.end(), n_00, 0b00);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // series.insert(series.end(), n_01, 0b01);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // series.insert(series.end(), n_10, 0b10);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // series.insert(series.end(), n_11, 0b11);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // std::array<int, 11> series {
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     0b00, 0b00,
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     0b01,
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     0b10, 0b10, 0b10, 0b10,
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     0b11, 0b11, 0b11, 0b11,
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // };
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // std::vector<uint32_t> ranges;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // do { // full permutation traversal
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     uint32_t range = 0;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     for (const auto x : series) // store every 2-bit
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //         (range <<= 2) |= x;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     ranges.emplace_back(range << offset);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // } while (std::next_permutation(series.begin(), series.end()));
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // do {
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     uint32_t range = 0;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     for (const auto x : series) // store every 2-bit
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //         (range <<= 2) |= x;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    //     ranges.emplace_back(range << offset);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // } while (std::ranges::next_permutation(series).found);
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // return ranges;
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
					 | 
					
  |