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