Functional programming 在函数式语言中生成所有排列

Functional programming 在函数式语言中生成所有排列,functional-programming,pattern-matching,ocaml,permutation,Functional Programming,Pattern Matching,Ocaml,Permutation,作为一个学术练习,我试图使用OCaml语言生成列表的所有可能排列,但不能使用for循环。我可以使用变量、递归、模式匹配和if-else控件 到目前为止,我的想法是:因为我可以使用递归,如果我想生成列表[1;2;3]的所有6个置换,那么我可以与h::t模式匹配,其中h是1,t是[2;3],假设我有[2;3]的所有置换。然后我想循环所有这些[2;3]的排列,在每个可能的坐标中插入1:0、1和2。例如,对于[2;3],我想生成[1;2;3]和[2;1;3]和[2;3;1],然后对于[3;2],我想生成

作为一个学术练习,我试图使用OCaml语言生成列表的所有可能排列,但不能使用for循环。我可以使用变量、递归、模式匹配和if-else控件

到目前为止,我的想法是:因为我可以使用递归,如果我想生成列表[1;2;3]的所有6个置换,那么我可以与h::t模式匹配,其中h是1,t是[2;3],假设我有[2;3]的所有置换。然后我想循环所有这些[2;3]的排列,在每个可能的坐标中插入1:0、1和2。例如,对于[2;3],我想生成[1;2;3]和[2;1;3]和[2;3;1],然后对于[3;2],我想生成[1;3;2]和[3;1;2]和[3;2;1]

然而,也存在一些明显的问题。一个是我需要告诉计算机,用这些工具,如何进行插入——但我已经知道了。我还需要“循环”所有较小的排列,然后循环它们的所有坐标,这是我不允许做的。这就是我被困的地方

以下是我所做的:

(* This successfully does insertion of v into l at pos.*)
let rec insert_at_i (v: int) (l: int list) (pos: int) : int list =
  begin match (l, pos) with
    | (_, 0) -> v::l 
    | ([], _) -> failwith "invalid insert_at_i"
    | (h::t, _) -> h::(insert_at_i v t (pos - 1))
  end

(* This finds the length of a list.*)
let rec len (l: int list) : int =
  begin match l with
    | [] -> 0
    | h::t -> (1 + (len t))
  end

(* Here I'm trying to take a value like 1 and a list like [2;3] and 
generate the list of all lists where 1 is inserted somewhere.  Since I 
can't loop, I tried thinking of a way to pattern-match, but it's not 
working out.  I tried to make extra parameters for basically keeping 
track of the recursion's results as I go, but I'm running into the 
problem that in a functional language like this, variables can't be re-
written with their side-effects stored, so to speak. *)
let rec insert_ith_at_i (v: int) (l: int list) (pos: int) (sofar: int list list): int list list =
  if (l = []) then [[v]]
  else if (pos > (len l)) then sofar
  else (insert_ith_at_i v l (pos + 1) )

欢迎提供任何指导或点击。

这里有一个解决方案-我首先定义了一些帮助函数:

let ( ^^ ) e ll = List.map (fun x -> e::x) ll
let rec permut l r =  /* l : left, r right */
    match r with 
    | [] -> [[]]
    | [x] -> x ^^ (permut [] l)
    | x::t -> let s = permut (x::l) t in 
              (x ^^ (permut [] (l@t))) @ s;;

 permut [] [1;2;3];
此函数用于向列表中包含的每个列表添加一个元素:

1 ^^ [[2; 3]; [3; 2]]  gives : [[1; 2; 3]; [1; 3; 2]]
然后使用
permut
功能:

let ( ^^ ) e ll = List.map (fun x -> e::x) ll
let rec permut l r =  /* l : left, r right */
    match r with 
    | [] -> [[]]
    | [x] -> x ^^ (permut [] l)
    | x::t -> let s = permut (x::l) t in 
              (x ^^ (permut [] (l@t))) @ s;;

 permut [] [1;2;3];
算法运行如下:

  • 选择第一个元素“x”
  • 计算剩余元素的所有置换
  • 将x添加到每个计算的排列中
  • 将此元素停在“左”列表中
  • 选择第二个元素
  • 计算其他元素的排列: 第一个在左边的列表中, “t”列表的剩余元素 ... 等等

(值得一提的是,任何循环都可以表示为递归。因此,您可以循环任何要循环的内容。)下次,请先尝试谷歌。@JaredSmith网站的未加载似乎暂时停止。另外,我在谷歌上也做过,在for循环中获得了很多点击率。@Addem我刚刚很好地加载了它(Chrome60Linux)。下面是指向ocaml impl的链接