Skip to content

Instantly share code, notes, and snippets.

@vrybas
Last active August 29, 2015 14:05
Show Gist options
  • Save vrybas/ec210d4ee934d26d39c6 to your computer and use it in GitHub Desktop.
Save vrybas/ec210d4ee934d26d39c6 to your computer and use it in GitHub Desktop.
require 'minitest/autorun'
require_relative 'complement'
class ComplementTest < MiniTest::Unit::TestCase
def test_rna_complement_of_cytosine_is_guanine
assert_equal 'G', Complement.of_dna('C')
end
def test_rna_complement_of_guanine_is_cytosine
assert_equal 'C', Complement.of_dna('G')
end
def test_rna_complement_of_thymine_is_adenine
assert_equal 'A', Complement.of_dna('T')
end
def test_rna_complement_of_adenine_is_uracil
assert_equal 'U', Complement.of_dna('A')
end
def test_rna_complement
assert_equal 'UGCACCAGAAUU', Complement.of_dna('ACGTGGTCTTAA')
end
def test_dna_complement_of_cytosine_is_guanine
assert_equal 'G', Complement.of_rna('C')
end
def test_dna_complement_of_guanine_is_cytosine
assert_equal 'C', Complement.of_rna('G')
end
def test_dna_complement_of_uracil_is_adenine
assert_equal 'A', Complement.of_rna('U')
end
def test_dna_complement_of_adenine_is_thymine
assert_equal 'T', Complement.of_rna('A')
end
def test_dna_complement
assert_equal 'ACTTGGGCTGTAC', Complement.of_rna('UGAACCCGACAUG')
end
end

Rna Transcription

Write a program that, given a DNA strand, returns its RNA complement (per RNA transcription).

Both DNA and RNA strands are a sequence of nucleotides.

The four nucleotides found in DNA are adenine (A), cytosine (C), guanine (G) and thymidine (T).

The four nucleotides found in RNA are adenine (A), cytosine (C), guanine (G) and uracil (U).

Given a DNA strand, its transcribed RNA strand is formed by replacing each nucleotide with its complement:

  • G -> C
  • C -> G
  • T -> A
  • A -> U

Source

Rosalind view source

@consti
Copy link

consti commented Sep 1, 2014

Not particularly interesting..

module Complement
  def self.of_dna(dna)
    dna.tr('GCTA', 'CGAU')
  end

  def self.of_rna(rna)
    rna.tr('CGAU', 'GCTA')
  end
end

@hybridknight
Copy link

long version

class Complement
  def self.dna_rna
    {
      'G' => 'C',
      'C' => 'G',
      'T' => 'A',
      'A' => 'U'
    }
  end

  def self.rna_dna
    Hash[self.dna_rna.to_a.map(&:reverse)]
  end

  def self.of_dna(d)
    d.chars.map{ |c| self.dna_rna[c] }.join
  end

  def self.of_rna(d)
    d.chars.map{ |c| self.rna_dna[c] }.join
  end
end

@vrybas
Copy link
Author

vrybas commented Sep 1, 2014

tried to keep it clean for future maintenance =^.^=

class Complement
  attr_reader :sequence, :complements

  DNA_COMPLEMENTS = { 'G' => 'C',
                      'C' => 'G',
                      'T' => 'A',
                      'A' => 'U' }

  def self.of_dna(dna)
    new(dna: dna).perform
  end

  def self.of_rna(rna)
    new(rna: rna).perform
  end

  def initialize(dna: nil, rna: nil)
    @sequence    = (dna || rna).chars
    @complements = (dna && DNA_COMPLEMENTS) ||
                   (rna && DNA_COMPLEMENTS.invert)
  end

  def perform
    sequence.collect { |nucleotide| complements[nucleotide] }.join
  end
end

@citizen428
Copy link

This is probably not the code I would really write ;-)

module Complement
  DNA_LOOKUP =  { 'G' => 'C', 'C' => 'G', 'T' => 'A', 'A' => 'U' }
  RNA_LOOKUP = DNA_LOOKUP.invert

  %i(dna rna).each do |s|
    define_singleton_method("of_#{s}") do |arg|
      arg.gsub(/(.)/, const_get("#{s.upcase}_LOOKUP"))
    end
  end
end

@vrybas
Copy link
Author

vrybas commented Sep 1, 2014

@hybridknight a little bit of duplication

@consti playing golf again ;)

@citizen428, (old-man-rant-mode-on)
on these challenges we're trying, I hope, to share best practices on how
you should write code :)

And pick up good habits to not introduce code smells. Come on guys!!!

↓↓↓

How you would write it for real?

@citizen428
Copy link

Here's the :trollface: rewrite of @consti's version:

module Complement
  def self.method_missing(m, *a, &b)
    m =~ /of_(dna|rna)/ && a[0].tr(*{ dna: ['GCTA', 'CGAU'], rna: ['CGAU', 'GCTA'] }[$1.to_sym])
  end
end

@wulab
Copy link

wulab commented Sep 1, 2014

Don't know Ruby has String#tr until seeing @const's solution. Mine just borrows it from Python.

class String
  def translate(from_str, to_str)
    IO.popen(["python", "-c", <<-CMD.gsub(/^\s{6}/,"")]) { |f| f.read.chomp }
      import string
      print '#{self}'.translate(string.maketrans('#{from_str}','#{to_str}'))
    CMD
  end
end

class Complement
  def self.of_dna(dna)
    dna.translate('GCTA','CGAU')
  end

  def self.of_rna(rna)
    rna.translate('CGAU','GCTA')
  end
end

@rhearnorth
Copy link

module Complement
  DNA_RNA = ['GCTA', 'CGAU']
  RNA_DNA = DNA_RNA.reverse

  def self.of_dna(dna)
    dna.tr(*DNA_RNA)
  end

  def self.of_rna(rna)
    rna.tr(*RNA_DNA)
  end
end

@vrybas
Copy link
Author

vrybas commented Sep 3, 2014

class Complement
  attr_reader :sequence, :complements

  DNA_COMPLEMENTS = { 'G' => 'C',
                      'C' => 'G',
                      'T' => 'A',
                      'A' => 'U' }

  def self.of_dna(dna)
    new(sequence: dna, complements: DNA_COMPLEMENTS).perform
  end

  def self.of_rna(rna)
    new(sequence: rna, complements: DNA_COMPLEMENTS.invert).perform
  end

  def initialize(sequence: nil, complements: nil)
    @sequence = sequence.chars
    @complements = complements
  end

  def perform
    sequence.collect { |nucleotide| complements[nucleotide] }.join
  end
end

@vrybas
Copy link
Author

vrybas commented Sep 4, 2014

class Complement < Struct.new(:sequence, :complements)
  DNA_COMPLEMENTS = { 'G' => 'C',
                      'C' => 'G',
                      'T' => 'A',
                      'A' => 'U' }

  def self.of_dna(dna)
    new(dna, DNA_COMPLEMENTS).perform
  end

  def self.of_rna(rna)
    new(rna, DNA_COMPLEMENTS.invert).perform
  end

  def perform
    sequence.tr("#{complements.keys}", "#{complements.values}")
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment