首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >方案中的Rosalind第三个问题

方案中的Rosalind第三个问题
EN

Code Review用户
提问于 2014-05-09 20:10:49
回答 2查看 804关注 0票数 3

我有一个命令式编程背景,我决定研究函数式编程,将其应用于Euler和Rosalind等网站上的问题。我选择的语言是“计划”(我用鸡肉)。可以看到,我才刚开始。

这是在Rosalind上发现的第三个问题,类似于

在DNA字符串中,符号'A‘和'T’是相互补充的,'C‘和'G’也是互补的。DNA串s的反向补码是通过倒转S的符号形成的字符串sc,然后取每个符号的补码(例如,"GTCA“的反向补码是"TGAC")。给出:一条长度不超过1000 bp的DNA串S。回报: s的反向补足。

下面是我的代码,它解决了这个问题:

代码语言:javascript
复制
(define (complement-of char)
  (cond
    ((eq? char #\A)
     #\T)
    ((eq? char #\T)
     #\A)
    ((eq? char #\C)
     #\G)
    ((eq? char #\G)
     #\C)
    (else
      char)))

(define (apply-complements dna-string)
  (reverse-list->string 
    (map complement-of 
     (string->list dna-string))))

(define (solve-problem infile-name outfile-name)
  (let ((outfile-port (open-output-file outfile-name))
        (infile-port (open-input-file infile-name)))
    (begin
      (write-line 
         (apply-complements (read-line infile-port)) outfile-port)
      (close-output-port outfile-port))))

有更好的方法来编写complement-of吗?也许是像字典那样的东西,或者在这个特殊的情况下,这会不会是太多的工作呢?

solve-problem是否适合于样式POV,还是更合适?

代码语言:javascript
复制
(define (solve-problem infile-name outfile-name)
  (let ((outfile-port (open-output-file outfile-name))
        (infile-port (open-input-file infile-name)))
    (begin
      (write-line 
         (apply-complements 
           (read-line infile-port)) 
         outfile-port)
      (close-output-port outfile-port))))

另外,是否有一种方法可以避免使用begin,同时仍然使事物看起来可读性?想到的唯一想法是提取一个函数,通过递归决定它是写到文件中还是关闭它。但这感觉很难直觉。

最后,我想听听我的代码还有什么其他问题。

EN

回答 2

Code Review用户

回答已采纳

发布于 2014-05-13 06:46:54

complement-of

编写complement-of的更好方法是使用case而不是cond

代码语言:javascript
复制
(case char
  ((#\A) #\T)
  ((#\T) #\A)
  ((#\C) #\G)
  ((#\G) #\C)
  (else char))

函数名一般不应该以-of结尾。(这是一种发音函数调用的方法,但它不是名称的一部分。) complement就足够了。(虽然有些方案有一个预先定义的函数,但最好不要与它发生冲突。)

提防eq? -它不可靠的字符。(这相当于Java的== on Character)。使用eqv?代替,除非你知道你在做什么。(case在内部使用eqv?。)

apply-complements

您可以通过使用小鸡的一个库来简化apply-complements(use (srfi 13))获取string-map,这与map类似,但可以节省转换为列表的费用。加上string-reverseapply-complements变得容易了。

...but --我不称它为apply-complements,因为这听起来像是对apply函数的引用。它返回其参数的反向补码,因此应该是它的名称:reverse-complement

如果您想使它更快,请尝试命令式方法:用make-string分配字符串,用dostring-set!循环。(知道如何编写命令式代码非常有用,即使在函数式语言中也是如此。)

solve-problem

solve-problem有一个非常普通的错误:您忘记关闭输入端口。)幸运的是,有些函数可以自动完成此操作,因此您不必记住:call-with-input-filecall-with-output-file。它们也更安全,因为它们像例外一样关闭非本地出口的端口。

let的主体是隐式begin,因此不需要solve-problem中的begin

格式化:当函数调用被分割为多行时,参数通常是对齐的,如下所示:

代码语言:javascript
复制
(write-line (apply-complements (read-line infile-port))
            outfile-port)

solve-problem有一个模糊的名字。如何描述一下它所做的事情,如reverse-complement-file?(名字是最好的评论。)

...however,reverse-complement只是您可能希望以这种方式应用于文件的许多操作之一。我可能会把它写成一个通用的transform-file,它将操作作为参数:(transform-file reverse-complement src dest)。或者,我会把它写成两个独立的操作,用于读写,因为它们通常是分开使用的。(我还会使用read-stringwrite-string,而不是read-linewrite-line,这样它们就可以处理多行文件。)

票数 3
EN

Code Review用户

发布于 2014-05-12 23:55:10

您可以使用字典/散列,但对于4种选择,这是过分的。

在我看来,apply-compliments只是compliment-of之上的地图。我将调用核心函数reverse-compliment。顺便说一句,如果我正确地阅读了问题描述,那么您可以反转字符串,然后应用赞美词,但您似乎是在恭维,然后又倒转。当然,从功能上来说,这并不重要。

老实说,我的方案有点生疏,但我认为既然您是let格式的,您就不需要begin了。

我也会用同样的方式布置solve-problem

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/49369

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档