exercism

Exercism - RNA Transcription

This post shows you how to get RNA Transcription exercise of Exercism.

Stevinator Stevinator
7 min read
SHARE
exercism dart flutter rna-transcription

Preparation

Before we click on our next exercise, let’s see what concepts of DART we need to consider

RNA Transcription Exercise

So we need to use the following concepts.

Maps

A Map is a collection of key-value pairs. Each key in a map is unique, and you can use keys to look up their corresponding values. Maps are perfect for creating lookup tables or translation dictionaries.

void main() {
  // Map with String keys and String values
  Map<String, String> complements = {
    'G': 'C',
    'C': 'G',
    'T': 'A',
    'A': 'U',
  };
  
  // Accessing values
  print(complements['G']); // C
  print(complements['T']); // A
  
  // Using map for translation
  String dna = 'G';
  String rna = complements[dna]!;
  print(rna); // C
}

String Split Method

The split() method divides a string into a list of substrings. When called with an empty string '', it splits the string into individual characters.

void main() {
  String dna = "GCTA";
  
  // Split into individual characters
  List<String> chars = dna.split('');
  print(chars); // [G, C, T, A]
  
  // Split by delimiter
  String sentence = "hello world";
  List<String> words = sentence.split(' ');
  print(words); // [hello, world]
}

Map Method

The map() method transforms each element in a collection. It takes a function that defines how to transform each element and returns an iterable of transformed values.

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // Double each number
  var doubled = numbers.map((n) => n * 2);
  print(doubled.toList()); // [2, 4, 6, 8, 10]
  
  // Transform strings
  List<String> letters = ['a', 'b', 'c'];
  var upper = letters.map((l) => l.toUpperCase());
  print(upper.toList()); // [A, B, C]
  
  // Using map with a lookup table
  Map<String, String> lookup = {'a': 'A', 'b': 'B', 'c': 'C'};
  List<String> input = ['a', 'b', 'c'];
  var transformed = input.map((e) => lookup[e]!);
  print(transformed.toList()); // [A, B, C]
}

ToList Method

The toList() method converts an iterable (like the result of map()) into a list. This is necessary when you need a concrete list rather than an iterable.

void main() {
  List<int> numbers = [1, 2, 3];
  
  // map() returns an Iterable, not a List
  var doubled = numbers.map((n) => n * 2);
  print(doubled.runtimeType); // MappedListIterable<int, int>
  
  // Convert to List
  List<int> doubledList = doubled.toList();
  print(doubledList.runtimeType); // List<int>
  print(doubledList); // [2, 4, 6]
}

String Join Method

The join() method combines all elements of a list into a single string. You can optionally specify a separator string between elements.

void main() {
  List<String> chars = ['G', 'C', 'T', 'A'];
  
  // Join without separator
  String result = chars.join();
  print(result); // GCTA
  
  // Join with separator
  String withSpace = chars.join(' ');
  print(withSpace); // G C T A
  
  // Join with custom separator
  String withDash = chars.join('-');
  print(withDash); // G-C-T-A
}

Method Chaining

Method chaining allows you to call multiple methods in sequence. Each method operates on the result of the previous one, creating a pipeline of transformations.

void main() {
  String dna = "GCTA";
  
  // Chain multiple operations
  String rna = dna
      .split('')           // ['G', 'C', 'T', 'A']
      .map((e) => e.toUpperCase())  // ['G', 'C', 'T', 'A']
      .toList()            // List<String>
      .join();             // "GCTA"
  
  print(rna);
  
  // More complex chain
  Map<String, String> lookup = {'G': 'C', 'C': 'G', 'T': 'A', 'A': 'U'};
  String result = "GCTA"
      .split('')
      .map((e) => lookup[e]!)
      .toList()
      .join();
  print(result); // CGUA
}

Introduction

You work for a bioengineering company that specializes in developing therapeutic solutions.

Your team has just been given a new project to develop a targeted therapy for a rare type of cancer.

Note

It’s all very complicated, but the basic idea is that sometimes people’s bodies produce too much of a given protein. That can cause all sorts of havoc.

But if you can create a very specific molecule (called a micro-RNA), it can prevent the protein from being produced.

This technique is called RNA Interference.

Instructions

Your task is to determine the RNA complement of a given DNA sequence.

Both DNA and RNA strands are a sequence of nucleotides.

The four nucleotides found in DNA are adenine (A), cytosine (C), guanine (G), and thymine (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

What is RNA Transcription?

RNA transcription is the process by which the information in a DNA sequence is copied into a complementary RNA sequence. In DNA, the base thymine (T) pairs with adenine (A), and guanine (G) pairs with cytosine (C). However, in RNA transcription, thymine (T) is replaced by uracil (U), so the pairing becomes: A pairs with U, and G pairs with C.

This is a fundamental process in molecular biology, as RNA serves as a template for protein synthesis. The RNA complement of a DNA strand is created by replacing each nucleotide according to specific rules.

— Molecular Biology

How can we transcribe DNA to RNA?

To transcribe DNA to RNA:

  1. Create a complement map: Use a Map to store the DNA-to-RNA complement mappings (G→C, C→G, T→A, A→U)
  2. Split the DNA string: Convert the DNA string into a list of individual characters
  3. Map each character: Transform each DNA nucleotide to its RNA complement using the map
  4. Join the results: Combine all the transformed characters back into a single string

The key insight is using a Map as a lookup table to translate each DNA nucleotide to its RNA complement, then using method chaining to process the entire string efficiently.

For example, with DNA strand “GCTA”:

  • Split: [‘G’, ‘C’, ‘T’, ‘A’]
  • Map: [‘C’, ‘G’, ‘A’, ‘U’] (using the complement map)
  • Join: “CGAU”

Solution

class RnaTranscription {
  String toRna(String dna) {
    Map rna = {
      'C': 'G',
      'G': 'C',
      'T': 'A',
      'A': 'U'
    };

    return dna.split('').map((e) => rna[e]).toList().join();
  }
}

Let’s break down the solution:

  1. Map rna = {...} - Creates a lookup table for DNA-to-RNA complements:

    • Maps each DNA nucleotide to its RNA complement
    • ‘C’ → ‘G’, ‘G’ → ‘C’, ‘T’ → ‘A’, ‘A’ → ‘U’
    • This map serves as a translation dictionary
  2. dna.split('') - Splits the DNA string into individual characters:

    • Converts “GCTA” into [‘G’, ‘C’, ‘T’, ‘A’]
    • Each character can now be processed individually
  3. .map((e) => rna[e]) - Transforms each DNA nucleotide to its RNA complement:

    • For each character e in the list, looks up its complement in the rna map
    • Returns an iterable of RNA nucleotides: [‘C’, ‘G’, ‘A’, ‘U’]
  4. .toList() - Converts the iterable to a concrete list:

    • Necessary because map() returns an iterable, not a list
    • Prepares the data for the join() method
  5. .join() - Combines all list elements into a single string:

    • Joins [‘C’, ‘G’, ‘A’, ‘U’] into “CGAU”
    • Returns the final RNA complement string

The solution uses method chaining to create a clean, functional pipeline: split → map → toList → join. This approach is concise and readable, transforming the entire DNA string to its RNA complement in a single expression.


You can watch this tutorial on YouTube. So don’t forget to like and subscribe. 😉

Watch on YouTube
Stevinator

Stevinator

Stevinator is a software engineer passionate about clean code and best practices. Loves sharing knowledge with the developer community.