我是OCaml的新手,所以我在基础知识方面遇到了一些麻烦。对于我的程序,我必须将核苷酸与其补体(G→C,C→G,A→T,T→A)匹配,以便找到双螺旋的另一半。一般的想法是DNA由2个互补的螺旋组成,每个螺旋都是核苷酸序列。目前,我正在尝试计算双螺旋的另一半。
到目前为止,我已经用枚举代表了核苷酸,并且我用一个与一个螺旋相对应的核苷酸列表代表了DNA。
type nucleotide =
| G
| C
| A
| T
type helix = nucleotide list
let rec complementary_helix (x:helix): helix =
| [G] -> [C]
| [C] -> [G]
| [A] -> [T]
| [T] -> [A]
end
我知道这里缺少一些东西,但我不知道如何去做。有人能引导我朝着正确的方向前进吗?
答案 0 :(得分:6)
你基本上只是缺少List.map
:
let complement = function
| G -> C
| C -> G
| A -> T
| T -> A
let complementary_helix (x: helix) : helix =
List.map complement x
(对于它的价值,没有必要指定类型.OCaml将推断类型。为文档指定它们是好的风格,但如果它们很明显则可能不是。)
修改强>
好吧,我想这是一个家庭作业问题,你应该使用递归来解决问题。
考虑递归的方法是你想要解决一小部分问题,这会给你一个较小的问题来解决。你将较小的问题传递给自己(在解决你的小块之前或之后)。你还需要知道问题何时变得如此之小,以至于没有更多的工作要做。
在您的情况下,小部分将翻译一个核苷酸到其补体。你正在做那个半好的(你有列表,你真的只想在单核苷酸上工作)。但是你没有把问题的其余部分传递给自己来递归解决。你也没有检查问题是否很小,无所事事。
对于列表上的函数,大约99%的时间通过将列表拆分为头部(单个元素)和尾部(列表小一个)来缩小问题。这对你有用。
修改2
作为列表递归的外观示例,这是一个将列表中所有整数相加的函数:
let rec sum l =
match l with
| [] -> 0
| head :: tail -> head + sum tail
这包含我描述的所有部分。 match
用于告诉问题何时是微不足道的(当列表为空时)并将列表拆分为头部和尾部。假设你有尾巴的总和(你可以递归地得到),答案是非常明显的。你只需要在这个总和上添加头部。你只需要问自己(几乎总是):如果我对列表的尾部有答案,我需要做些什么才能将它与头部结合起来?