2017-03-08 75 views
0

我正在寫一個算法來刪除重疊,給定一個範圍的行(我稱之爲「行」,因爲在這種情況下,術語「範圍」的含糊不清)。如何轉換範圍,與範圍-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)。下面是這個問題的圖形表示:

Overlap Removal

這是問題的一個可能的解決方案:

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?

我在考慮使用修改後的view::chunk(N),其中增量的大小是1(而不是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

忍者。用'ranges :: transform'算法調用'for'循環來獲得額外的勝利。 –

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

頻道,爲您的原始範圍的變換視圖,然後遍歷爲了轉化視圖。

從min int的高位開始。確保整體壽命足夠長。

Live example(想不出一個更簡單的方法從一個數組轉換回本身...)

+0

此外,如果我是正確的,該視圖將只能迭代一次。 – Jarod42

+0

@ Jarod42第二次,你會假設前一組元素不會與之重疊。 ;) – Yakk