更新:我不能使用任何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
);
);;
问题吗
mono list
应返回非递减列表。问题吗
有什么想法吗?
由于
答案 0 :(得分:3)
解决这类问题的好方法是强迫自己 以数学方式表达你正在寻找正式的内容 正确的方法。通过一些培训,这通常会让你 与您将要编写的最终程序接近的描述。
我们正在尝试定义包含的函数incr li
严格增加li
的子序列。正如Jeffrey Scoffield所问,
你可能正在寻找
longest
这样的子序列:这是一个有趣且非平凡的算法
问题很好,但考虑到你是初学者
我想你的老师要求更简单的东西。这是我的
建议更简单的规范:你正在寻找所有的
大于它们之前的所有元素的元素
列表。
生成易于转换的数学定义的好方法
算法是通过归纳推理:定义一个属性
自然数P(n)
就前身P(n-1)
或定义而言
在列表中列出该属性的给定列表上的属性
少元素。考虑您要定义incr [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
添加了
这两个精确的定义当然可以推广到
任何长度,他们有两种不同的方式来写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)