作为礼物,我感到困惑。它由4个并排排列的立方体组成。每个立方体的面是四种颜色之一。
为了解决这个难题,必须对多维数据集进行定向,以使所有四个多维数据集的顶部都不同,它们的正面都不同,背面都不同,底部都不同。左右两侧无所谓。
我的伪代码解决方案是:
创建每个的表示
立方体。
获取所有可能的方向
每个立方体(每个有24个)。
获取以下所有可能的组合
每个立方体的方向。
查找方向的组合
满足解决方案。
我使用F#中的伪代码实现解决了这个难题,但是我对步骤3的方式不满意:
let problemSpace =
seq { for c1 in cube1Orientations do
for c2 in cube2Orientations do
for c3 in cube3Orientations do
for c4 in cube4Orientations do
yield [c1; c2; c3; c4] }
上面的代码非常具体,只能计算出四个方向序列的笛卡尔积。我开始考虑为n个方向序列编写它的方法。
我想出了(从现在开始,所有代码都应在F#交互中很好地执行):
// Used to just print the contents of a list.
let print =
Seq.fold (fun s i -> s + i.ToString()) "" >> printfn "%s"
// Computes the product of two sequences - kind of; the 2nd argument is weird.
let product (seq1:'a seq) (seq2:'a seq seq) =
seq { for item1 in seq1 do
for item2 in seq2 do
yield item1 |> Seq.singleton |> Seq.append item2 }
产品功能可以像这样使用...
seq { yield Seq.empty }
|> product [ 'a'; 'b'; 'c' ]
|> product [ 'd'; 'e'; 'f' ]
|> product [ 'h'; 'i'; 'j' ]
|> Seq.iter print
...导致...
let productn (s:seq<#seq<'a>>) =
s |> Seq.fold (fun r s -> r |> product s) (seq { yield Seq.empty })
[ [ 'a'; 'b'; 'c' ]
[ 'd'; 'e'; 'f' ]
[ 'h'; 'i'; 'j' ] ]
|> productn
|> Seq.iter print
这正是我想要的用法。 productn完全具有我想要的签名并且可以工作。
但是,使用product涉及到讨厌的行seq {yield Seq.empty},这很不直观:
一系列值(seq )
一系列值序列(seq )
第二个参数似乎不正确。
这个奇怪的界面被productn很好地隐藏了,但是无论如何仍然困扰着我。
是否有更好,更直观的方法来一般性地计算n个序列的笛卡尔积?是否有任何内置函数(或它们的组合)可以做到这一点?
最佳答案
使用递归:n个列表{L1..LN}的笛卡尔乘积是将L1中的每个元素添加到列表{L2..LN}的笛卡尔积的每个子列表时得到的列表的集合。
let rec cart1 LL =
match LL with
| [] -> Seq.singleton []
| L::Ls -> seq {for x in L do for xs in cart1 Ls -> x::xs}
例:
> cart1 [[1;2];[3;4;5];[6;7]] |> Seq.toList;;
val it : int list list =
[[1; 3; 6]; [1; 3; 7]; [1; 4; 6]; [1; 4; 7]; [1; 5; 6]; [1; 5; 7]; [2; 3; 6];
[2; 3; 7]; [2; 4; 6]; [2; 4; 7]; [2; 5; 6]; [2; 5; 7]]
[1; 2] [3; 4; 5]和[6; 7]的笛卡尔积是{1的并集,附加到购物车[[3; 4; 5]; [6; 7]]中的每个列表和{2附加到购物车[[3; 4; 5]; [6; 7]]}中的每个列表中。这是match语句中的第二个子句。
关于f# - 如何计算F#中n个序列的笛卡尔积?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3334429/