Functional programming Erlang中列表的笛卡尔幂

Functional programming Erlang中列表的笛卡尔幂,functional-programming,erlang,Functional Programming,Erlang,我试图将erlang Mastermind解算器编码为一个练习(我是一个完全的新手,但我认为这对于函数式语言来说是一个有趣的练习) 我希望它尽可能一般,所以我觉得我需要一个笛卡尔幂函数。比如: cart_pow([a,b],2) -> [[a,a],[a,b],[b,a],[b,b]] cart_pow([a,b],3) -> [[a,a,a],[a,a,b],[a,b,a],[a,b,b],[b,a,a],[b,a,b],[b,b,a],[b,b,b]] 我想不出一个纯粹的函数式

我试图将erlang Mastermind解算器编码为一个练习(我是一个完全的新手,但我认为这对于函数式语言来说是一个有趣的练习)

我希望它尽可能一般,所以我觉得我需要一个笛卡尔幂函数。比如:

cart_pow([a,b],2) -> [[a,a],[a,b],[b,a],[b,b]]
cart_pow([a,b],3) -> [[a,a,a],[a,a,b],[a,b,a],[a,b,b],[b,a,a],[b,a,b],[b,b,a],[b,b,b]]
我想不出一个纯粹的函数式(递归、映射、折叠…)解决方案。
有什么线索吗?如果它是懒惰的,就有奖励

您可能会发现这个堆栈溢出问题很有帮助,它涉及在函数式语言中生成列表的笛卡尔幂。这个问题针对的是F#,但评论中也有一个Haskell示例:

来自Haskell实现:

cart_pow(Xs, N) -> 
    sequence(lists:duplicate(N, Xs)).

sequence([]) ->
    [[]];
sequence([Xs|Xss]) ->
    [[X|Xs1] || X <- Xs, Xs1 <- sequence(Xss)].
PS:甚至更好:

sequence(Xss) ->
    lists:foldl(fun(Xs, A) -> [[X|Xs1] || X <- Xs, Xs1 <- A] end, [[]], Xss).
序列(Xss)->

列表:foldl(fun(Xs,A)->[[X|Xs1]| | X由@Ed'ka提供的解决方案简洁而漂亮,但尽管如此,它的复杂性是
O(N)

我建议您考虑,它在功率计算中提供了
O(log(N))
复杂性。使用此技术,笛卡尔功率可以通过以下方式实现:

%%入口点
购物车(列表,N)->
Tmp=[[X]| | X
货币清单;
当N rem 2==0->
Tmp=mul(CurrList,CurrList),
购物车(Tmp,Tmp,N部门2);
购物车(初始列表,当前列表,N)->
Tmp=购物车(初始列表,当前列表,N-1),
mul(初始列表,Tmp)。
mul(L1,L2)->

[X++Y | | | X mul是缺少的部分。我无法让它返回正确的结构,主要是因为我不明白正确的输入不是([a,b],[a,b]),而是函数
mul
计算出的两个列表的笛卡尔积中的([[a],[b],[[a],[b]])。您可能注意到这里使用的列表串联语法(运算符
++
)。因此,它意味着-该函数仅适用于列表列表。这就是为什么您必须调用
mul([[a],[b],[[a],[b])
而不是
mul([a,b],[a,b])
。如果查看入口点(函数
cart/2
),您可能会注意到,我将输入列表转换为列表列表(通过将每个元素包装在它自己的列表中:
[[X]| | X如果
++
操作符是O(1),那么它将是O(log(N)),但不幸的是它是O(N)(其中N是左参数的长度),因此实际上,您只是用一个
++
替换了多个
[[X]
。您的解决方案确实运行得更快(恒定的差异)与我的第一个版本相比,但我怀疑这是由于第二种情况下的tail调用造成的。例如,如果我使我的解决方案tail递归(请参阅我的更新),它将比您的更快(同样,一个常量差异)。
1> timer:tc(fun() -> length(tmp1:cart([0,1], 20)) end).
{383939,1048576}
2> timer:tc(fun() -> length(tmp1:cart_pow([0,1], 20)) end).
{163932,1048576}
sequence(Xss) ->
    lists:foldl(fun(Xs, A) -> [[X|Xs1] || X <- Xs, Xs1 <- A] end, [[]], Xss).
1> c(my_module).
{ok,my_module}
2> 
2> my_module:cart([0,1], 2).
[[0,0],[0,1],[1,0],[1,1]]
3> 
3> my_module:cart([0,1], 3).
[[0,0,0],
 [0,0,1],
 [0,1,0],
 [0,1,1],
 [1,0,0],
 [1,0,1],
 [1,1,0],
 [1,1,1]]