19
\$\begingroup\$

Introduction

RNA is the less famous cousin of DNA. Its main purpose is to control the production of proteins in cells through a process called translation. In this challenge, your task is to implement a part of this process where the RNA is split into codons.

This challenge is thematically related, but concentrates on another part of the translation process.

Codons

We will think of RNA as a long string over the alphabet of base pairs, AUCG. In translation, RNA is split into non-overlapping chunks of three base pairs, called codons. The process begins at a start codon, AUG, and ends at a stop codon, one of UAA, UAG or UGA. Each codon (except the stop codons) corresponds to an amino acid, and the resulting string of amino acids forms the protein.

Input

Your input is a non-empty string of RNA.

Output

Your output is the list of codons in which the RNA is split, in any reasonable format. In this simplified model, the process begins at the leftmost start codon AUG, which is included in the output. It ends when a stop codon is encountered, or when we run out of RNA. If the input contains no start codon, the output shall be an empty list.

Examples

Consider the input sequence

ACAUGGAUGGACUGUAACCCCAUGC

The parsing begins at the leftmost occurrence of AUG, at index 2. It continues as follows:

AC AUG GAU GGA CUG UAA CCCCAUGC
   *   ^   ^   ^   +

The codon marked with * is the start codon, and those marked with ^ are also part of the output. The stop codon is marked with +. The correct output is

AUG,GAU,GGA,CUG

For the shorter input

ACAUGGAUGGACUGU

the process goes

AC AUG GAU GGA CUG U
   *   ^   ^   ^

This time, a stop codon is not encountered, so the process stops when we run out of base pairs. The output is the same as above.

Rules and scoring

You can write a full program of a function. The lowest byte count wins, and standard loopholes are disallowed.

Test cases

GGUACGGAUU -> 
GGCGAAAUCGAUGCC -> AUG
ACAUGGAUGGACUGU -> AUG,GAU,GGA,CUG
AUGACGUGAUGCUUGA -> AUG,ACG
UGGUUAGAAUAAUGAGCUAG -> AUG,AGC
ACAUGGAUGGACUGUAACCCCAUGC -> AUG,GAU,GGA,CUG
CUAAGAUGGCAUGAGUAAUGAAUGGAG -> AUG,GCA
AAUGGUUUAAUAAAUGUGAUAUGAUGAUA -> AUG,GUU
UGUCACCAUGUAAGGCAUGCCCAAAAUCAG -> AUG
UAUAGAUGGUGAUGAUGCCAUGAGAUGCAUGUUAAU -> AUG,GUG,AUG,AUG,CCA
AUGCUUAUGAAUGGCAUGUACUAAUAGACUCACUUAAGCGGUGAUGAA -> AUG,CUU,AUG,AAU,GGC,AUG,UAC
UGAUAGAUGUAUGGAUGGGAUGCUCAUAGCUAUAAAUGUUAAAGUUAGUCUAAUGAUGAGUAGCCGAUGGCCUAUGAUGCUGAC -> AUG,UAU,GGA,UGG,GAU,GCU,CAU,AGC,UAU,AAA,UGU
\$\endgroup\$
8
  • 13
    \$\begingroup\$ The relationship of DNA to RNA to protein was once explained to me in computing terms that I could understand: DNA equates to a program on a hard disk; RNA equates to that program loaded into memory; and protein equates to the output data produced as a result of that program running. \$\endgroup\$ Jan 16, 2016 at 1:42
  • 4
    \$\begingroup\$ The Dogma of molecular biology is "DNA makes RNA makes protein." So DNA is fairly rare, and RNA is less famous, but far more common. Protein is most common of all. \$\endgroup\$ Jan 16, 2016 at 1:53
  • 1
    \$\begingroup\$ @DigitalTrauma: As a geneticist I need to point out that this analogy is woefully inadequate to describe the reality of how DNA works. DNA is not some dead thing waiting to be transcribed into RNA so it can do something. \$\endgroup\$ Jan 16, 2016 at 10:08
  • \$\begingroup\$ What actually occurs in practice if a piece of mRNA terminates before a stop codon (as in the simple example), meaning no stop triplet for a release factor to bind to? \$\endgroup\$
    – nanofarad
    Jan 16, 2016 at 11:52
  • 1
    \$\begingroup\$ @Jack hard disk contents are not necessarily dead things either - upgrades, auto updates, etc, though of course not self-healing to the extent I understand DNA to be. But you're right - It is a weak analogy. However I think it got my non-geneticist self a little closer to a layman understanding \$\endgroup\$ Jan 16, 2016 at 17:31

10 Answers 10

11
\$\begingroup\$

Retina, 39 38 32 30 bytes

M!`AUG|\B\G...
U(AA|AG|GA)\D*

The trailing linefeed is significant.

Output as a linefeed-separated list.

Try it online.

Explanation

M!`AUG|\B\G...

This is match stage which turns the input into a linefeed-separated list of all matches (due to the !). The regex itself matches every codon starting from the first AUG. We achieve this with two separate options. AUG matches unconditionally, so that it can start the list of matches. The second match can be any codon (... matches any three characters), but the \G is a special anchor which ensures that this can only match right after another match. The only problem is that \G also matches at the beginning of the string, which we don't want. Since the input consists only of word characters, we use \B (any position that is not a word boundary) to ensure that this match is not used at the beginning of the input.

U(AA|AG|GA)\D*

This finds the first stop codon, matched as U(AA|AG|GA) as well as everything after it and removes it from the string. Since the first stage split the codons into separate lines, we know that this match is properly aligned with the start codon. We use \D (non-digits) to match any character, since . wouldn't go past the linefeeds, and the input won't contain digits.

\$\endgroup\$
5
\$\begingroup\$

Haskell, 115 112 bytes

import Data.Lists
fst.break(\e->elem e["UAA","UAG","UGA"]||length e<3).chunksOf 3.snd.spanList((/="AUG").take 3)

Usage example:

*Main> ( fst.break(\e->elem e["UAA","UAG","UGA"]||length e<3).chunksOf 3.snd.spanList((/="AUG").take 3) ) "AUGCUUAUGAAUGGCAUGUACUAAUAGACUCACUUAAGCGGUGAUGAA"
["AUG","CUU","AUG","AAU","GGC","AUG","UAC"]

How it works:

                spanList((/="AUG").take 3)  -- split input at the first "AUG"
             snd                            -- take 2nd part ("AUG" + rest)
     chunksOf 3                             -- split into 3 element lists
fst.break(\e->                              -- take elements from this list
           elem e["UAA","UAG","UGA"]||      -- as long as we don't see end codons
           length e<3)                      -- or run out of full codons 
\$\endgroup\$
2
\$\begingroup\$

Perl 5 -n, 40 bytes

map/UAA|UAG|UGA/?last:say,/AUG|\B\G.../g

Try it online!

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

Vyxal 3, 25 bytes

"ᶠx„ẋİ⁻/3Ŀ:ƛ'u"\ᵇ„o+c]Ṙƒh

Try it Online!

There's my 26 25 byter

old explanation:

"ᶠx„ẋİ⁻/3Ŀ:ƛ'u"\ᵇ„o+=a]Ṙƒh­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏⁠‏​⁡⁠⁡‌⁢​‎⁠⁠⁠⁠⁠‎⁡⁠⁢⁢‏‏​⁡⁠⁡‌⁣​‎⁠⁠⁠⁠‎⁡⁠⁢⁣‏⁠⁠⁠⁠‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁣⁤‏⁠‎⁡⁠⁢⁢⁡‏⁠‎⁡⁠⁢⁢⁢‏⁠‎⁡⁠⁢⁢⁣‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁤⁣‏⁠‎⁡⁠⁤⁤‏⁠‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏⁠‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁢⁢⁤‏⁠‎⁡⁠⁢⁣⁡‏⁠‎⁡⁠⁢⁣⁢‏‏​⁡⁠⁡‌­
"ᶠx„ẋ                       # ‎⁡The first index of "aug"
     İ                      # ‎⁢Slice from here to the end
      ⁻                     # ‎⁣Split into parts of length 3
       /3Ŀ:                 # ‎⁤Keep only those whose length is 3 and duplicate
           ƛ        =a]     # ‎⁢⁡for each codon, does it equal any of...
                  o         # ‎⁢⁢overlapping pairs of....
              "\ᵇ„          # ‎⁢⁣The string "aaga" --> ["aa", "ag", "ga"]
            'u              # ‎⁢⁤with a "u" prepended to each ["uaa", "uag", "uga"]
                       Ṙƒh  # ‎⁣⁡partition before truthy indices, take the first item.
💎

Created with the help of Luminespire.

\$\endgroup\$
2
  • \$\begingroup\$ i feel like 26 is doable here but i cant seem to make it work for every test case \$\endgroup\$
    – pacman256
    Feb 15 at 12:59
  • \$\begingroup\$ old me had a skill issue and was looking in the wrong place \$\endgroup\$
    – pacman256
    Mar 6 at 3:20
1
\$\begingroup\$

JavaScript 88 82 70 69 chars

s=>/AUG(...)+?(?=(U(AA|AG|GA)|$))/.exec(s)[0].match(/.../g).join(",")

Usage Example:

(s=>/AUG(...)+?(?=(U(AA|AG|GA)|$))/.exec(s)[0].match(/.../g).join(","))("ACAUGGAUGGACUGUAACCCCAUGC")
\$\endgroup\$
4
  • \$\begingroup\$ Doesn't this fail for input without a stop codon? \$\endgroup\$
    – Flambino
    Jan 16, 2016 at 23:11
  • 1
    \$\begingroup\$ You're right, I didn't see that was an option, fixing \$\endgroup\$ Jan 16, 2016 at 23:13
  • \$\begingroup\$ Try s=>/AUG(...)+?(?=(U(AA|AG|GA)|$))/.exec(s)[0].match(/.../g). \$\endgroup\$ Jan 17, 2016 at 2:43
  • \$\begingroup\$ Still fails for stop codons. (Try test case 3) \$\endgroup\$
    – user81655
    Jan 17, 2016 at 2:55
1
\$\begingroup\$

Ruby, 97 95 78 75 62 bytes

->(r){r.scan(/AUG|\B\G.../).join(?,).sub(/,U(AA|AG|GA).*/,'')}

I don't golf much, so I'm sure it can be improved.

Edit: Stole Borrowed Martin Büttner's excellent \B\G trick

\$\endgroup\$
1
\$\begingroup\$

Python 2, 185 bytes

i=input()
o=[]
if i.find('AUG')>=0:i=map(''.join,zip(*[iter(i[i.find('AUG'):])]*3))
else:print "";exit()
for j in i:
 if j not in['UGA','UAA','UAG']:o+=[j]
 else:break
print ','.join(o)

Explanation Set i to input. Split it from 'AUG' to the end. Split into strings of three. Check if stop codon, and cut.

Try it here

\$\endgroup\$
0
1
\$\begingroup\$

MATL, 57 bytes

j'AUG(...)*?(?=(UAA|UAG|UGA|.?.?$))'XXtn?1X)tnt3\-:)3[]e!

This uses current version (9.3.1) of the language/compiler.

Input and output are through stdin and stdout. The output is separated by linebreaks.

Example

>> matl
 > j'AUG(...)*?(?=(UAA|UAG|UGA|.?.?$))'XXtn?1X)tnt3\-:)3[]e!
 >
> ACAUGGAUGGACUGUAACCCCAUGC
AUG
GAU
GGA
CUG

EDIT (June 12, 2016): to adapt to changes in the language, [] should be removed. The link below includes that modification

Try it online!

Explanation

The code is based on the regular expression

AUG(...)*?(?=(UAA|UAG|UGA|.?.?$))

This matches substrings starting with AUG, containing groups of three characters (...) and ending in either UAA, UAG, or UGA; or ending at the end of the string, and in this case there may be one last incomplete group (.?.?$). Lookahead ((?=...)) is used so that the stop codons are not part of the match. The matching is lazy (*?) in order to finish at the first stop codon found, if any.

j                                     % input string
'AUG(...)*?(?=(UAA|UAG|UGA|.?.?$))'   % regex
XX                                    % apply it. Push cell array of matched substrings
tn?                                   % if non-empty
1X)                                   % get first substring
tnt3\-:)                              % make length the largest possible multiple of 3
3[]e!                                 % reshape into rows of 3 columns
                                      % implicit endif
                                      % implicit display
\$\endgroup\$
0
\$\begingroup\$

Scala 2, 170 156 bytes

A port of @nimi's Haskell answer in Scala.

Saved 14 bytes thanks to @pacman256


Golfed version. Attempt This Online!

s=>{val q=s.indexOf("AUG");if(q>=0){val c=s.drop(q).grouped(3).toSeq;c.takeWhile(c=>c.size==3&& !Seq("UAA","UAG","UGA").contains(c))}else Seq.empty[String]}

Ungolfed version. Attempt This Online!

object RNASequenceProcessor {

  def main(args: Array[String]): Unit = {
    val rnaSequence = "AUGCUUAUGAAUGGCAUGUACUAAUAGACUCACUUAAGCGGUGAUGAA"
    val codingRegion = findCodingRegion(rnaSequence)
    println("["++codingRegion.mkString(",")++"]")
  }

  def findCodingRegion(sequence: String): Seq[String] = {
    // Find the start of the coding region (first occurrence of "AUG")
    val startOfCoding = sequence.indexOf("AUG")
    if (startOfCoding != -1) {
      // Extract the sequence from "AUG" onward
      val codingSequence = sequence.drop(startOfCoding)
      
      // Split the sequence into codons (chunks of 3 nucleotides)
      val codons = codingSequence.grouped(3).toSeq
      
      // Take codons until a stop codon is encountered or the codon length is less than 3
      codons.takeWhile(codon => codon.length == 3 && !Seq("UAA", "UAG", "UGA").contains(codon))
    } else {
      Seq.empty[String] // Return an empty sequence if "AUG" is not found
    }
  }
}
\$\endgroup\$
2
0
\$\begingroup\$

JavaScript (Node.js), 67 bytes

s=>[/AUG(...)*?(?=UA[AG]|UGA|.?.?$)|$/.exec(s)[0].match(/.../g)]+''

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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