没有List.function的OCaml非递减列表

时间:2013-02-10 07:14:38

标签: recursion ocaml

更新:我不能使用任何List.function的东西。

我是OCaml的新手,我正在学习这门课程,我应该从一系列值中计算非减少值的列表。

因此,例如我有一个清单[1; 2; 3; 1; 2; 7; 6]

所以接受列表的函数mono返回以下内容:

# mono [1; 2; 3; 1; 2; 7; 6];;
- : int list = [1; 2; 3; 7]

我执行以下操作:

let rec calculateCheck value lst = (
    match lst with
     [] -> true
    | x :: xs -> (
        if (value < x) then
            false
        else
            calculateCheck value xs
    )
);;


let rec reverse_list lst = (

    match lst with
     [] -> []
    | x :: xs -> (
        reverse_list xs @ [x]
    )
);;

let shouldReverse = ref 1;; 

let cancelReverse somelist lst = (
    shouldReverse := 0;
    reverse_list lst
);;

let rec mono lst = (
    let somelist = ref lst in
        if (!shouldReverse = 1) then
            somelist := cancelReverse somelist lst
        else
            somelist := lst;

    match !somelist with
     [] -> []
    | x :: xs -> (
        if (calculateCheck x xs) then
            [x] @ mono xs
        else
            [] @ mono xs
    );
);;

问题吗

  1. 由于shouldReverse,这只能工作一次。
  2. 我无法扭转价值; mono list应返回非递减列表。
  3. 问题吗

    1. 任何简单的方法吗?
    2. 具体如何获取列表的子集。对于例如对于[1; 2; 3; 5; 6],我想要[1; 2; 3]作为5的输出,以便我可以递归地解决这个问题。另一件事,你可以有一个列表[1; 2; 3; 5; 6; 5] ::所以对于第二个5,输出应为[1; 2; 3; 5; 6]。
    3. 有什么想法吗?

      由于

1 个答案:

答案 0 :(得分:3)

解决这类问题的好方法是强迫自己 以数学方式表达你正在寻找正式的内容 正确的方法。通过一些培训,这通常会让你 与您将要编写的最终程序接近的描述。

我们正在尝试定义包含的函数incr li 严格增加li的子序列。正如Jeffrey Scoffield所问, 你可能正在寻找 longest 这样的子序列:这是一个有趣且非平凡的算法 问题很好,但考虑到你是初学者 我想你的老师要求更简单的东西。这是我的 建议更简单的规范:你正在寻找所有的 大于它们之前的所有元素的元素 列表。

生成易于转换的数学定义的好方法 算法是通过归纳推理:定义一个属性 自然数P(n)就前身P(n-1)或定义而言 在列表中列出该属性的给定列表上的属性 少元素。考虑您要定义incr [x1; x2; x3; x4]。您 可以用incr [x1; x2; x3]x4表示,也可以用。{ x1incr [x2; x3; x4]的条款。

  • incr [x1;x2;x3;x4]incr[x1;x2;x3],如果更大则为x4 比列表中的所有元素,或等价的, incr[x1;x2;x3]

  • 的最大元素
  • incr [x1;x2;x3;x4]incr[x2;x3;x4]所有元素 小于x1已被删除(它们并不比所有人都大 他们之前的元素),x1添加了

这两个精确的定义当然可以推广到 任何长度,他们有两种不同的方式来写incr

(* `incr1` defines `incr [x1;x2;x3;x4]` from `incr [x1;x2;x3]`,
   keeping as intermediate values `subli` that corresponds to
   `incr [x1;x2;x3]` in reverse order, and `biggest` the biggest
   value encountered so far. *)
let incr1 li =
  let rec incr subli biggest = function
    | [] -> List.rev subli
    | h::t ->
      if h > biggest
      then incr (h::subli) h t
      else incr subli biggest t
  in
  match li with
    | [] -> []
    | h::t -> incr [h] h t

(* `incr2` defines `incr [x1;x2;x3;x4]` from `incr [x2;x3;x4]`; it
   needs no additional parameter as this is just a recursive call on
   the tail of the input list. *)
let rec incr2 = function
  | [] -> []
  | h::t ->
    (* to go from `incr [x2;x3;x4]` to `incr [x1;x2;x3;x4]`, one
       must remove all the elements of `incr [x2;x3;x4]` that are
       smaller than `x1`, then add `x1` to it *)
    let rec remove = function
      | [] -> []
      | h'::t ->
        if h >= h' then remove t
        else h'::t
    in h :: remove (incr2 t)