在输入向量的笛卡尔积中创建第n个元素的元组

史蒂夫·洛里默

我有一个python函数,它在许多输入数组的笛卡尔积中返回第n个元素

def prod(n, arrs):
    out = []

    for i,arr in enumerate(arrs):
        denom = numpy.prod([ len(p) for p in arrs[i+1:] ], dtype=int)
        idx = n // denom % len(arr)
        out.append( arr[idx] )

    return out

这很好用:

a = [ 1000, 1100, 1200, 1300, 1400 ]
b = [ 1.0, 1.5, 2.0, 2.5, 3.0, 3.5 ]
c = [ -2, -1, 0, 1, 2 ]

for n in range(20, 30):
    i = prod(n, [a, b, c])
    print(n, i)
[1000, 3.0, -2]
[1000, 3.0, -1]
[1000, 3.0, 0]
[1000, 3.0, 1]
[1000, 3.0, 2]
[1000, 3.5, -2]
[1000, 3.5, -1]
[1000, 3.5, 0]
[1000, 3.5, 1]
[1000, 3.5, 2]

现在我想将其翻译为C ++(最高标准C ++-17)

template<typename... Ts>
auto prod(std::size_t n, const std::vector<Ts>&... vs) 
    -> std::tuple<const std::decay_t<typename std::vector<Ts>::value_type>&...>
{
    // template magic here
}

有人可以帮助我使用上述公式构造元组所需的模板魔术吗?

N·希德

其他答案已经提到了索引技巧。这是我的尝试,请尽可能直接从您的python代码进行转换:

template <typename T, std::size_t... I>
auto prod_impl(std::size_t n, T tuple, std::index_sequence<I...>) {
    std::array sizes{ std::size(std::get<I>(tuple))... };
    auto enumerator = [&sizes,n](std::size_t i, auto&& arr) -> decltype(auto) {
        auto denom = std::accumulate(std::begin(sizes) + i + 1, std::end(sizes), 1, std::multiplies<>{});
        auto idx = (n / denom) % std::size(arr);
        return arr[idx];
    };

    return std::forward_as_tuple(enumerator(I, std::get<I>(tuple))...);
}

template<typename... Ts, typename Is = std::index_sequence_for<Ts...>>
auto prod(std::size_t n, const std::vector<Ts>&... vs) {
    return prod_impl(n, std::forward_as_tuple(vs...), Is{});
}

(实时示例:http : //coliru.stacked-crooked.com/a/a8b975c29d429054

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章