Basic DNA Coding Exercise

Viewed 67

I recently failed an interview in which I was thrown a Python coding question out of the blue. I'm currently learning Python, and if I came upon the same question again or a similar question I want to be able to answer it.

The question was as follows:

Write a function which takes as its input a string containing the letters: [A, C, G, T]; and outputs all the 3-letter subsequences found in the input and the frequency with which they occur. For example, if the input string was "ACTACTTAC", the output would be something like:

ACT: 2
CTA: 1
TAC: 2
CTT: 1
TTA: 1

I came up with some ideas after the fact and I had wondered if a solution like this works, or is there a better way of doing it?

def Determine_DNA(dna_list):
    n = len(dna_list[0])
    A = [0]*n
    T = [0]*n
    G = [0]*n
    C = [0]*n
    for dna in dna_list:
        for index, base in enumerate(dna):
            if base == 'A':
                A[index] += 1
            elif base == 'C':
                C[index] += 1
            elif base == 'G':
                G[index] += 1
            elif base == 'T':
                T[index] += 1
    return A, C, G, T
2 Answers

@mousetail mentioned in the comments using collections.Counter. Here is an example of that:

import collections

def dna_freq(dnaseq):
    seq_list = []
    for i in range(2, len(dnaseq)):
        seq_list.append(dnaseq[i-2:i+1])
    return dict(collections.Counter(seq_list))

print(dna_freq("ACTACTTAC"))

{'ACT': 2, 'CTA': 1, 'TAC': 2, 'CTT': 1, 'TTA': 1}

That could be code-golf'd, if hard to read code is your thing:

 def dna_freq(dnaseq):
     return dict(collections.Counter([dnaseq[i-2:i+1] for i in range(2, len(dnaseq))]))

Example using zip from the comments, which feels more approachable than list comprehension. It does give a slightly different, but totally usable output.

def dna_freq(dnaseq):
    return dict(collections.Counter(zip(dnaseq, dnaseq[1:], dnaseq[2:])))

This works for your case:

dna = "ACTACTTAC"
LEN = 3
d = set()

for i in range(len(dna)-LEN):
    k = dna[i:i+LEN]
    if not k in d:
        print(f'{k}: {dna.count(k)}')
        d.add(k)

Output:

ACT: 2
CTA: 1
TAC: 2
CTT: 1
TTA: 1
Related