OCaml 中的交错
Interleaving in OCaml
我正在尝试创建一个函数来交织一对三元组,例如 ((6, 3, 2), ( 4, 5 ,1)) 并从这个交织中创建一个 6 元组。
我做了一些研究,但可以理解交错应该如何工作,所以我自己尝试了一些东西,最终得到了一个创建 6 元组但不是以正确的交错方式创建的代码。这是我的代码
let interleave ((a, b, c), (a', b', c')) =
let sort2 (a, b) = if a > b then (a, b) else (b, a) in
let sort3 (a, b, c) =
let (a, b) = sort2 (a, b) in
let (b, c) = sort2 (b, c) in
let (a, b) = sort2 (a, b) in
(a, b, c) in
let touch ((x), (y)) =
let (x) = sort3 (x) in
let (y) = sort3 (y) in
((x),(y)) in
let ((a, b, c), (a', b', c')) = touch ((a, b, c), (a', b', c')) in
(a, b', a', b, c, c');;
有人可以向我解释一下如何使用哪些函数实现适当形式的交错。我还没有了解递归和列表,以防你问我为什么要这样做。
已经谢谢了。
问题陈述使用了 "max" 一词,但未对其进行定义。如果您使用 OCaml 的内置 compare
函数作为您的定义,它会使用 lexicographic order。因此,您希望 6 元组中第一个位置的(6 个值中的)最大值,下一个第二大值,依此类推。
考虑到您之前掌握的元组排序技能,这应该很容易。
就其价值而言,保留两个三元组的身份似乎没有太大价值。一旦进入最外层的函数,您就可以将 6 个值作为 6 元组使用。或者在我看来是这样。
更新
从您的示例(可能应该在开头就给出 :-) 可以很清楚地知道您被要求做什么。您希望最终得到一个序列,其中原始元组的元素按其原始顺序排列,但它们可以任意交错。这通常称为 "shuffle"(或合并)。您必须按字典顺序找到具有最大值的随机播放。
如果你推理出来,这相当于从两个元组的前面取最大的值并将其放在输出中的下一个。
使用列表容易得多。
现在我明白你的最终目标是什么了。 . .
由于 n 元素的元组对于不同的 n 是不同类型的,您需要定义辅助函数来操作不同大小的元组。
一种方法,基本上模仿列表上的递归函数(但需要许多额外的函数,因为元组都有不同的类型),是有两组辅助函数:
将值添加到现有元组前面的函数:prepend_to_2
,一直到 prepend_to_5
。例如,
let prepend_to_3 (a, (b, c, d)) = (a, b, c, d)
交错两个元组的函数,每个元组的大小最大为 3:interleave_1_1
、interleave_1_2
、interleave_1_3
、interleave_2_2
、interleave_2_3
,以及 interleave_3_3
。 (请注意,我们不需要 interleave_2_1
,因为我们可以用相反顺序的参数调用 interleave_1_2
。)例如,
let interleave_2_2 ((a, b), (a', b')) =
if a > a'
then prepend_to_3 (a, interleave_1_2 (b, (a', b')))
else prepend_to_3 (a', interleave_1_2 (b', (a, b)))
(你知道它是如何工作的吗?)
那么 interleave
就是 interleave_3_3
.
有了列表和递归,这会简单得多,因为单个函数可以对任意长度的列表进行操作,因此您不需要同一逻辑的多个不同副本。
我正在尝试创建一个函数来交织一对三元组,例如 ((6, 3, 2), ( 4, 5 ,1)) 并从这个交织中创建一个 6 元组。 我做了一些研究,但可以理解交错应该如何工作,所以我自己尝试了一些东西,最终得到了一个创建 6 元组但不是以正确的交错方式创建的代码。这是我的代码
let interleave ((a, b, c), (a', b', c')) =
let sort2 (a, b) = if a > b then (a, b) else (b, a) in
let sort3 (a, b, c) =
let (a, b) = sort2 (a, b) in
let (b, c) = sort2 (b, c) in
let (a, b) = sort2 (a, b) in
(a, b, c) in
let touch ((x), (y)) =
let (x) = sort3 (x) in
let (y) = sort3 (y) in
((x),(y)) in
let ((a, b, c), (a', b', c')) = touch ((a, b, c), (a', b', c')) in
(a, b', a', b, c, c');;
有人可以向我解释一下如何使用哪些函数实现适当形式的交错。我还没有了解递归和列表,以防你问我为什么要这样做。 已经谢谢了。
问题陈述使用了 "max" 一词,但未对其进行定义。如果您使用 OCaml 的内置 compare
函数作为您的定义,它会使用 lexicographic order。因此,您希望 6 元组中第一个位置的(6 个值中的)最大值,下一个第二大值,依此类推。
考虑到您之前掌握的元组排序技能,这应该很容易。
就其价值而言,保留两个三元组的身份似乎没有太大价值。一旦进入最外层的函数,您就可以将 6 个值作为 6 元组使用。或者在我看来是这样。
更新
从您的示例(可能应该在开头就给出 :-) 可以很清楚地知道您被要求做什么。您希望最终得到一个序列,其中原始元组的元素按其原始顺序排列,但它们可以任意交错。这通常称为 "shuffle"(或合并)。您必须按字典顺序找到具有最大值的随机播放。
如果你推理出来,这相当于从两个元组的前面取最大的值并将其放在输出中的下一个。
使用列表容易得多。
现在我明白你的最终目标是什么了。 . .
由于 n 元素的元组对于不同的 n 是不同类型的,您需要定义辅助函数来操作不同大小的元组。
一种方法,基本上模仿列表上的递归函数(但需要许多额外的函数,因为元组都有不同的类型),是有两组辅助函数:
将值添加到现有元组前面的函数:
prepend_to_2
,一直到prepend_to_5
。例如,let prepend_to_3 (a, (b, c, d)) = (a, b, c, d)
交错两个元组的函数,每个元组的大小最大为 3:
interleave_1_1
、interleave_1_2
、interleave_1_3
、interleave_2_2
、interleave_2_3
,以及interleave_3_3
。 (请注意,我们不需要interleave_2_1
,因为我们可以用相反顺序的参数调用interleave_1_2
。)例如,let interleave_2_2 ((a, b), (a', b')) = if a > a' then prepend_to_3 (a, interleave_1_2 (b, (a', b'))) else prepend_to_3 (a', interleave_1_2 (b', (a, b)))
(你知道它是如何工作的吗?)
那么 interleave
就是 interleave_3_3
.
有了列表和递归,这会简单得多,因为单个函数可以对任意长度的列表进行操作,因此您不需要同一逻辑的多个不同副本。