2
\$\begingroup\$

I've been going through some of the exercises over on exercism and this is one of my solutions: a basic RNA/DNA transcriber. I was happy enough at first but now, looking at it again, the solution looks very repetitive to me.

The two methods below are needed because there are tests to ensure we've implemented them. It's just the code inside the methods I'm trying to refactor.

  def self.of_dna(dna)
    if dna.include? 'U'
      raise ArgumentError.new('Incorrect nucleotide detected. Please enter a DNA sequence.')
    else
      return dna.gsub(/[GCTA]/, 'G' => 'C', 'C' => 'G', 'T' => 'A', 'A' => 'U')
    end
  end

  def self.of_rna(rna)
    if rna.include? 'T'
      raise ArgumentError.new('Incorrect nucleotide detected. Please enter an RNA sequence')
    else
      return rna.gsub(/[GCAU]/, 'G' => 'C', 'C' => 'G', 'A' => 'T', 'U' => 'A')
    end
  end

As you can see, in one method I'm performing the following substitutions:

'G' for 'C' 'C' for 'G' 'A' for 'T' 'U' for 'A'

In the other method it's the reverse. Can anyone point me in the right direction towards simplifying this and making it more concise?

\$\endgroup\$
2
\$\begingroup\$

To make it more concise and readable:

  • you can use tr instead of regex as @200_success pointed out
  • use Ruby's trailing if construct to short-circuit input errors
  • omit the return which is unnecessary
  • omit the message about entering a DNA sequence. User input is not the responsibility of these methods. The message should be closer to where the input is handled.

Here's what it condenses to:

 def self.of_dna(dna)
   raise ArgumentError, 'Incorrect nucleotide' if dna.include? 'U'
   dna.tr('GCTA', 'CGAU')
 end
\$\endgroup\$
1
\$\begingroup\$

A more appropriate function for this kind of substitution is String#tr.

\$\endgroup\$
  • \$\begingroup\$ something along the lines of: dna.tr('[GCTA]', '[CGAU]') ? \$\endgroup\$ – SoSimple May 12 '15 at 15:34
  • \$\begingroup\$ @SoSimple You don't need the brackets - #tr doesn't use regular expressions. So just rna = dna.tr('GCTA', 'CGAU') and you're done \$\endgroup\$ – Flambino May 12 '15 at 16:42
  • \$\begingroup\$ This is exactly what tr is for. \$\endgroup\$ – Mark Thomas May 12 '15 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.