通过递归函数交换两个列表(Ocaml)

时间:2012-09-27 18:34:26

标签: recursion ocaml

我面临着相当大的挑战,希望你能提供一些帮助。

我经常尝试和搜索,但没有成功。

问题在于:

两个清单

List1 : [a1; a2; ...; an]
List2 : [b1; b2; ...; bn]

返回两个列表中可能存在的所有交错列表的函数是什么功能。对每个列表中的顺序进行处理。

例如:

myFunction [1; 2] ['a'; 'b'; 'c'] = [ 
    [1; 2; 'a'; 'b'; 'c']; 
    [1; 'a'; 2; 'b'; 'c']; 
    [1; 'a'; 'b'; 2; 'c']; 
    [1; 'a'; 'b'; 'c'; 2]; 
    ['a'; 1; 2; 'b'; 'c']; 
    ['a'; 1; 'b'; 2; 'c']; 
    ['a'; 1; 'b'; 'c'; 2]; 
    ['a'; 'b'; 1; 2; 'c']; 
    ['a'; 'b'; 1; 'c'; 2]; 
    ['a'; 'b'; 'c'; 1; 2] 
]

对于那些注意到的人来说,它基本上是考虑2个并发程序,并且当2个程序启动时所有执行都是可能的(1总是在2之前,a总是在b之前和c之前,否则,所有交错都是可能的)

我希望我很清楚,你可以帮助我。

非常感谢你。

2 个答案:

答案 0 :(得分:5)

由于这是家庭作业,这里有一些提示:

1)。该函数将采用两个相同类型'a list的列表并返回'a list list

val interleave: 'a list -> 'a list -> 'a list list

2)。如果一个列表为空,则结果是由另一个列表组成的单例列表 3)。假设您希望在两个非空列表interleavex::xs上执行y::ys。有两种交错。第一种类型有x作为结果列表的头部,您可以将x放入从interleave xs (y::ys)返回的任何列表的开头。第二种类型有y作为新头,您可以将y添加到从interleave (x::xs) ys获取的任何列表中。

通过这些提示,我认为您可以使用一些模式匹配案例创建递归函数来解决问题。

答案 1 :(得分:3)

(* Each interleaving of non-empty lists lst1 = [x1; x2; ...; xm]
   and lst2 = [y1; y2; ...; yn] begins either with x1 or with y1.
   Thus we may get all the interleavings as follows:

   1. Compute all interleavings of [x2; ...; xm] and [y1; ...; yn]
      and prepend x1 to each one of them.

   2. Compute all interleavings of [x1; ...; xm] and [y2; ...; yn]
      and prepend y1 to each one of them.

   Append the lists obtained in steps 1 and 2 to get all possible
   interleavings. The border cases is when either one of the lists
   is empty, but that is easy to figure out. Here is the corresponding
   code.
*)

let rec interleave lst1 lst2 =
  match lst1, lst2 with
    | [], ys -> [ys]
    | xs, [] -> [xs]
    | x :: xs, y :: ys ->
        (List.map (fun zs -> x :: zs) (interleave xs (y::ys))) @
        (List.map (fun zs -> y :: zs) (interleave (x::xs) ys))

测试用例:

# interleave [1;2] [100;200;300] ;;
- : int list list =
[[1; 2; 100; 200; 300]; [1; 100; 2; 200; 300]; [1; 100; 200; 2; 300];
[1; 100; 200; 300; 2]; [100; 1; 2; 200; 300]; [100; 1; 200; 2; 300];
[100; 1; 200; 300; 2]; [100; 200; 1; 2; 300]; [100; 200; 1; 300; 2];
[100; 200; 300; 1; 2]]

注意:在Ocaml中,列表是单态的,因此我们不能像问题中所建议的那样交错字符串和整数。或者以不同的方式,我们将不得不使用它 总和类型。