Recursion OCaml不带list.function的非递减列表

Recursion OCaml不带list.function的非递减列表,recursion,ocaml,Recursion,Ocaml,更新:我不能使用任何列表。函数的东西 我是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

更新:我不能使用任何列表。函数的东西

我是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
    );
);;
我做了以下工作:

# 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
    );
);;
让rec计算检查值lst=(
匹配lst与
[]->正确
|x::xs->(
如果(值 []
|x::xs->(
反向列表xs@[x]
)
);;
let shouldReverse=ref 1;;
让Cancel反转somelist lst=(
shouldReverse:=0;
反向列表
);;
设rec mono lst=(
让somelist=ref lst进入
如果(!shouldReverse=1),则
somelist:=取消反向somelist lst
其他的
somelist:=lst;
匹配!与某人列表匹配
[] -> []
|x::xs->(
如果(calculateCheck x xs),则
[x] @mono-xs
其他的
[]@mono-xs
);
);;
问题?

  • 这只工作一次,因为shouldReverse
  • 我无法逆转价值<代码>单声道列表应返回非递减列表
  • 问题?

  • 有什么简单的方法吗
  • 特别是如何获取列表的子集。例如,对于[1;2;3;5;6],我希望[1;2;3]作为5的输出,这样我就可以递归地解决这个问题。另一件事是,您可以将列表设置为[1;2;3;5;6;5]::因此,对于第二个5,输出应该是[1;2;3;5;6]
  • 有什么想法吗


    谢谢

    解决这类问题的一个好办法是强迫自己 以数学的方式,正式地表达你所寻找的东西 正确的方法。经过一些训练,这通常会让你 接近您将要编写的最终程序的描述

    我们试图定义一个函数
    incr li
    ,它包含
    li
    的严格递增子序列。正如杰弗里·斯科菲尔德所问, 您可能正在寻找 这样的子序列:这是一个有趣且不平凡的算法 这个问题研究得很好,但考虑到你是个初学者 我想你的老师要求的是更简单的东西。这是我的 一个更简单规范的建议:您正在寻找所有 元素,这些元素大于 名单

    这是一个很好的方法来产生数学定义,很容易转向 算法是通过归纳推理:定义一个属性 自然数
    P(n)
    在前面的
    P(n-1)
    中,或定义 给定列表中的一个属性,就一个列表中的该属性而言 更少的元素。假设您想定义<代码> iCCR[x1;x2;x3;x4] < /代码>。你 可以用
    incr[x1;x2;x3]
    x4
    表示,也可以用
    x1
    incr[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
      已被删除(它们不大于所有 前面的元素),并添加了
      x1

    这两个精确的定义当然可以推广到 任意长度,它们提供了两种不同的写入方法

    (* `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)
    

    不管它值多少钱,很难帮上忙,因为问题陈述根本不清楚。很容易计算任何列表的非递减子列表。空列表是一个非递减列表。任何只有一个元素的列表都是非递减列表。最有可能的是,要求比这更具体。你应该找到一个(可能是几个)最长的非递减子列表吗?不。事实上,我本可以让自己更清楚。很抱歉。我真正想要的是得到一份后备名单。比如说,我需要删除列表中的重复项,只保留第一个。例如,对于列表[1;2;2;4;3;1;3;5],答案应该是:[1;2;4;3;5]。考虑上面列表中的第二个1:没有办法让我回到列表中,看看是否存在1。在这个新的(完全不同的)例子中,如果你只把你的部分计算结果传递给每个递归调用,你就不需要回到原来的列表中。您可以检查部分结果,查看该值是否已经存在。在FP中,将累积的答案传递给每个通话是一项标准技术。(事实上,这也是扭转列表的好方法。)非常感谢gasche。我想,我已经了解了这背后的哲学。有几件事我还不确定,但我想我能解决。谢谢@谢谢你的客气话。我必须警告您,这里有一个教学陷阱:为什么在第一个函数中将
    subli
    以“相反顺序”传递给
    incr
    ,实践者会很清楚(这是Jeffrey描述的“传递累加器参数”的一个经典实例),但作为初学者,您可能会发现这很麻烦。这是一个需要更多练习才能明白的想法,但我觉得我没能优雅地解释清楚。事实上,在进一步思考时,我完全迷失了方向。也许是睡眠;我不知道。我想把我的部分计算机结果传递给递归调用,但我没有遵循代码。对不起。@flippex17:嗯,可能是睡眠不足吧!我认为第二个版本对初学者来说应该更容易理解,所以也许你应该从那里开始。@flippex17:如果你愿意,我可以用实际的工作代码替换漏洞,但我认为你更愿意