Как преобразовать диапазон, пара за парой, с range-v3?
Я пишу алгоритм для удаления перекрытий, учитывая диапазон строк (я называю это "линиями" из-за неоднозначности термина "диапазон" в данном случае).
Это как line
похоже:
struct line {
int begin, width;
int end() const { return begin + width; }
};
Пример: учитывая три строки (0,3), (1,2) и (5,1), я ожидаю получить (0,3), (3,2) и (5,1) после преобразования. Вот графическое представление этой проблемы:
Это одно из возможных решений проблемы:
auto removeOverlap(std::pair<line, line> input)
{
// keeps first line untouched and shifts the second line to the end of the first one, if necessary
return std::pair<line, line>{std::get<0>(input), {std::max(std::get<0>(input).end(), std::get<1>(input).begin), std::get<1>(input).width}};
}
int main(int argc, char *argv[])
{
std::array<line, 3> lines{{{0,3},{1,2},{5,1}}};
for(int i = 0; i < lines.size()-1; ++i)
{
std::tie(lines[i], lines[i+1]) = removeOverlap(std::make_pair(lines[i], lines[i+1]));
}
assert(lines[0].begin == 0);
assert(lines[1].begin == 3);
assert(lines[2].begin == 5);
Мой вопрос: как я могу сделать это с помощью range-v3?
Я думаю об использовании модифицированного view::chunk(N)
в котором размер приращения равен 1 (вместо N). Но я действительно не знаю, как действовать с этого момента.
2 ответа
Вы можете сделать:
auto pair_view =
ranges::view::zip(lines | ranges::view::take(lines.size() - 1),
lines | ranges::view::drop(1));
for (auto&& p : pair_view)
{
p = removeOverlap(p);
}
auto push_highwater = [](int& highwater){
return [&](line l) {
l.begin = (std::max)(highwater, l.begin);
highwater = l.end();
return l;
};
};
Подайте это в трансформируемое представление вашего исходного диапазона, затем переберите трансформированное представление по порядку.
Начните с высокой воды мин. Убедитесь, что Int живет достаточно долго.
Живой пример (не мог найти более простой способ преобразования массива обратно в себя...)