函数式编程在 C++1z 中每三分之一递增整数序列?

Functional programming incrementing integer sequence on every third one in C++1z?

我可以编写一个 C++ 程序来使用 for 循环生成此输出:

(200, 150)
(199, 150)
(198, 150)
(197, 149)
(196, 149)
(195, 149)
(194, 148)
(193, 148)
(192, 148)
(191, 147)

使用函数式编程技术(特别是 C++ Streams C++14 库)我可以做到这一点。

#include <iostream>
#include "../Streams-master/source/Stream.h"
using namespace stream;
using namespace stream::op;
int main(){
    MakeStream::counter(200,-1)
        | zip_with(MakeStream::counter(150,-1))
        | limit(10)
        | for_each([](std::tuple<int, int>&& tup) {
            std::cout << tup << std::endl;
            });
    }

生产:

(200, 150)
(199, 149)
(198, 148)
(197, 147)
(196, 146)
(195, 145)
(194, 144)
(193, 143)
(192, 142)
(191, 141)

在 C++1z 中,每三列递增第二列的函数式编程技术是什么?

我不懂 C++,但也许在 Haskell 中草拟一个解决方案会有帮助?您可以在 Haskell:

中以这种方式编写递减整数列表
list1, list2 :: [Integer]
list1 = [200, 199..]
list2 = [150, 149..]

这些列表中的第一个评估为您正在构建的对的第一个元素。例如使用take函数提取前15个元素:

>> take 15 list1
[200,199,198,197,196,195,194,193,192,191,190,189,188,187,186] 

但是,第二个没有您想要的"skip":

>> take 15 list2
[150,149,148,147,146,145,144,143,142,141,140,139,138,137,136]

但是,我们可以在该列表的基础上更进一步:

list3 :: [Integer]
list3 = concatMap triplicate list2
    where triplicate n = [n, n, n]

或者使用标准库中的replicate函数:

list4 :: [Integer]
list4 = concatMap (\n -> replicate 3 n) list2

concatMap/replicate 这一步似乎是您所缺少的。示例输出:

>>> take 15 list4
[150,150,150,149,149,149,148,148,148,147,147,147,146,146,146]

现在,将它们与 zip 函数放在一起:

solution :: [Integer]
solution = zip [200, 199..] (concatMap (\n -> replicate 3 n) [150, 149..])

使用示例:

>>> mapM_ print (take 10 solution) 
(200,150)
(199,150)
(198,150)
(197,149)
(196,149)
(195,149)
(194,148)
(193,148)
(192,148)
(191,147)

请注意,C++ Streams API 具有此 Haskell 代码中的大部分(如果不是全部的话)操作(模数细节差异),因此解决方案应该翻译得很好:

  1. Haskell concatMap = C++ flat_map
  2. Haskell replicate = C++ repeat

根据 Luis Casillas Haskel 的回答和注释,添加 | flat_map([](int x){return MakeStream::repeat(x,3);})) :

#include <iostream>
#include "../Streams-master/source/Stream.h"
using namespace stream;
using namespace stream::op;
int main(){
    MakeStream::counter(200,-1)
    | zip_with(MakeStream::counter(150,-1)
        | flat_map([](int x){return MakeStream::repeat(x,3);}))
    | limit(10)
    | for_each([](auto tup) {std::cout << tup << std::endl;});
    }