aminoseq(X) :-
aminoseq(X, []).
aminoseq([], X) :-
print(X).
aminoseq([A|B], X) :-
aminotodna(A, Y),
append(X, Y, Z),
aminoseq(B, Z).
此Prolog代码允许用户输入列表并将该列表与预设的aminotodna列表组合并显示两个结果。我不明白哪一部分做了什么...我想知道将来的工作。 任何帮助表示赞赏。
答案 0 :(得分:2)
首先,aminoseq/1
调用aminoseq/2
,暗示aminoseq/2
的第二个参数是某种状态变量,其初始值为空列表。
接下来,aminoseq/2
以递归方式处理第一个参数,即一个列表。当列表变空时(我假设它是氨基酸列表或其他东西)它只打印第二个参数。这是aminoseq/2
的第一个条款。
接下来,aminoseq/2
的第二个条款。它试图将氨基酸A
(第一个参数列表中的当前第一个项目)转换为其他东西(DNA,我猜)并将其称为Y
。然后它将X
(当前"状态"参数)附加到Y
,给出Z
,然后将其与参数列表中的其余项重复。< / p>
我对生物学知之甚少,但我可以猜测,这里要发生的是你想要传递氨基酸列表并找回DNA碱基列表。这不是一种非常有效的方法(特别是,我有点讨厌你在aminoseq/2
结束时打印),但它会完成任务。我建议您使用trace/0
检查输出,看看Prolog正在尝试做什么。
什么部分正在做什么?所有的实际工作都在aminotodna/2
完成,这是从氨基酸到密码子的实际表格。这段代码的其余部分只是管理数据结构,列表。
我会更像这样解决问题:
amino_dna(gly, [g,g,g]).
amino_dna(gly, [g,g,a]).
% ...
amino_dna(lys, [a,a,g]).
% ...
amino_dna(ser, [t,c,g]).
amino_dna(pro, [c,c,c]).
amino_acid_dna_sequence([], []).
amino_acid_dna_sequence([Acid|Acids], [C1,C2,C3|DNA]) :-
amino_dna(Acid, [C1,C2,C3]),
amino_acid_dna_sequence(Acids, DNA).
我发现这更直接:少了append/3
敲打,没有I / O与逻辑关系的混合。它可以在两个方向上驱动:
?- amino_acid_dna_sequence([lys,ser,pro], X).
X = [a, a, g, t, c, g, c, c, c].
?- amino_acid_dna_sequence([lys,gly,pro], X).
X = [a, a, g, g, g, g, c, c, c] ;
X = [a, a, g, g, g, a, c, c, c].
?- amino_acid_dna_sequence(Aminos, [a,a,g,t,c,g,c,c,c]).
Aminos = [lys, ser, pro] ;
false.
答案 1 :(得分:2)
除了丹尼尔写的(+1)之外,我还有以下两点:
从关系名称中删除_to_
。由于可以在所有方向上使用纯关系,因此使用暗示方向的名称是没有意义的。
在描述列表时始终考虑使用dcg。它们通常使您的代码更容易阅读,因为它们需要更少的参数和变量名称。
我因此建议:
amino_dna(gly) --> [g,g,g].
amino_dna(gly) --> [g,g,a].
% ...
amino_dna(lys) --> [a,a,g].
% ...
amino_dna(ser) --> [t,c,g].
amino_dna(pro) --> [c,c,c].
amino_sequence([]) --> [].
amino_sequence([Acid|Acids]) -->
amino_dna(Acid),
amino_sequence(Acids).
示例查询:
?- length(Ls, _), phrase(amino_sequence(As), Ls).
As = Ls, Ls = [] ;
As = [gly],
Ls = [g, g, g] ;
As = [gly],
Ls = [g, g, a] ;
As = [lys],
Ls = [a, a, g] ;
As = [ser],
Ls = [t, c, g] ;
etc.
请注意使用length/2
进行公平查点。