如何解决OCaml:处理列表元素和 int 之间奇偶校验的递归函数
这个函数应该接受两个参数一个列表和一个整数。如果列表中的元素和数字“a”奇偶校验相等,则必须将它们相加,否则应减去这两个数字。
计算应按此顺序进行:
- 一开始,残值r就是a的值,
- lst 的每个元素 e(按照列表给出的顺序)影响残差值:如果 e 和 r 具有相同的奇偶性(都是奇数或都是偶数),那么新的 r' 等于r + e,如果不是那么它应该等于 r - e 的减法,
- 最后一个 r 是预期的结果。
举个例子:
par [4;7;3;6] 5
should return -1,it would work as follows :
5 and 4 have a different parity so we subtract -> 5 - 4 = 1
1 and 7 are both odd,so we add them together -> 1 + 7 = 8
8 and 3 have a different parity -> 8 - 3 = 5
Finally,5 and 6 have different parity -> 5 - 6 = -1
我在下面想到了这样的事情:
let rec par lst a =
match lst with
| [] -> 0
| h::t -> if (h mod 2 == 0 && a mod 2 == 0) || (h mod 2 == 1 && a mod 2 == 1) then a + h
| h::t -> if (h mod 2 == 0 && a mod 2 == 1) || (h mod 2 == 1 && a mod 2 == 0) then a - h :: par t a ;;
EDIT1:这是我从编译器得到的错误:
第 4 行,字符 83-88:错误:此表达式的类型为 int 但 表达式应为 unit 类型,因为它是 a 的结果 没有其他分支的条件
我们的想法是仅使用以下预定义函数 List.hd、List.tl 和 List.length 来构建此函数。
我上面的提议有什么令人不安的地方以及如何补救?任何人都可以帮我解决这个问题吗?
编辑 2: 我能够用 if...then... else 语法(不是我所知道的最好的 OCaml)做需要的事情,但我个人有时在理解模式匹配时遇到更多困难。无论如何,这就是我得到的:
let rec par lst a = (* Sorry it might hurt some sensible eyes *)
if List.length lst = 0 then a
else
let r = if (List.hd lst + a) mod 2 == 0 then (a + (List.hd lst))
else (a - (List.hd lst)) in
par (List.tl lst) r ;;
val par : int list -> int -> int = <fun>
欢迎提出建议并帮助将其放入模式匹配语法中。
解决方法
您的代码无法编译。你有没有尝试编译它?您是否阅读了编译器产生的错误和警告?您能否将它们添加到您的问题中?
关于您的代码的一些评论:
-
| h::t -> if ... then ...
应该是| h::t when ... -> ...
; -
(h mod 2 == 0 && a mod 2 == 0) || (h mod 2 == 1 && a mod 2 == 1)
可以简化为(h - a) mod 2 == 0
; - 编译器喜欢知道匹配是详尽无遗的;特别是,你不需要在匹配的第三行重复测试(只有在第二行测试为假时才会读取第三行);
- 您在匹配的第二行中缺少递归调用;
- 在匹配的第三行中,您返回的是一个列表而不是一个数字(编译器应该明确告诉您该类型不匹配!您没有阅读编译器错误消息吗?);
- 在匹配的第一行,如果列表为空,则返回 0。当您到达列表末尾时,您确定 0 是要返回的值吗?您计算的残值如何?
- 一旦您将此版本的代码修复为递归函数,我建议您尝试使用
List.fold_left
编写解决相同问题的代码,而不是像您一样使用List.hd
和List.tl
正在建议。
当我第一次写我的答案时,我包含了你的代码的一个固定版本,但我认为如果我提供解决方案而不是让你弄清楚,我会伤害你。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。