#pragma once #include #include #include // Using boost flat set was faster than std::set. namespace detail { template auto same_group(Field const & field, typename Field::Position const & p, typename Field::Position const & q){ return field.get(p) == field.get(q); } template void cluster_expand(Field const & field, typename Field::Position const & p, boost::container::flat_set& ret){ for(auto&& q : field.neighbors(p)){ if(!same_group(field, p, q)) continue; if(ret.insert(q).second){ cluster_expand(field, q, ret); } } } } template auto cluster_at(Field const & field, typename Field::Position const & p){ boost::container::flat_set ret; ret.reserve(10); // speed improvement of 20% ret.insert(p); detail::cluster_expand(field, p, ret); return ret; } template auto all_clusters(Field const & field){ boost::container::flat_set()))> ret; ret.reserve(10); for(auto&& p : field.all_positions()){ if(field.empty(p)) continue; ret.insert(cluster_at(field, p)); } return ret; } template auto make_empty(Field field, Cluster const & c){ using namespace std; for(auto&& p : c){ field.get(p) = 0; } field.collapse(); return field; }