2017-03-08 5 views
0

私は、ある範囲の線があれば、重なりを取り除くアルゴリズムを書いています(私は、この場合は "範囲"という用語のあいまいさのために "線"と呼んでいます)。 、考えると三行(0,3)、(1,2)と(5,1)は、私が得ることを期待する(0:range-v3とペアでペアを変換する方法は?

struct line { 
    int begin, width; 
    int end() const { return begin + width; } 
}; 

例:

これはlineがどのように見えるかです3)、(3,2)、(5,1)に変換する。ここでは、この問題をグラフに表したものである:

Overlap Removal

これは、問題のための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); 

私の質問:どのように私は範囲-V3を使用してこれを行うことができますか?

増分のサイズが1(Nではなく)である変更済みview::chunk(N)を使用することを考えています。しかし、私は実際にこの点から進める方法を知らない。

答えて

3
あなたが行うことができます

:元の範囲のビュー変換には、順番に変換ビューを反復処理すること

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); 
} 

Demo

+1

忍者。 'for'ループを' ranges :: transform'アルゴリズムの呼び出しに置き換えて、余分な勝利を得てください。 –

1
auto push_highwater = [](int& highwater){ 
    return [&](line l) { 
    l.begin = (std::max)(highwater, l.begin); 
    highwater = l.end(); 
    return l; 
    }; 
}; 

フィード。

min intのハイウォーターで開始します。 intの長さが十分に長くなるようにします。

Live example(バック自体に配列から変換するための簡単な方法を見つけ出すことができませんでした...)

+0

さらに、私が正しい場合、ビューは1回だけ反復可能になります。 – Jarod42

+0

@ Jarod42 2回目は、前の要素のセットが重ならないと仮定します。 ;) – Yakk

関連する問題