-1

The problem is to first reverse the string. Then swap "T" for "A", and vice versa, and "G" for "C", and vice versa. I have no problem reversing the string. The problem is replacing T with A and vice versa and also with G and C and vice versa since the replace methods cancel each other out.

Here is my code:

s = str(raw_input("Enter a string: ")) 
reversed = s[::-1] 

if "T" and "A" and "G" and "C" in reversed: 
    reversed.replace("A", "T") 
    reversed.replace("T", "A")
    reversed.replace("C", "G")
    reversed.replace("G", "C") 

print reversed 

Any help or suggestions would be greatly appreciated.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • it might be best to step through each character one by one and replace rather than performing ````replace()```` on the entire string. Something like ````for character in reversed:```` – Kivak Wolf Sep 22 '15 at 21:38
  • 1
    You have two obvious problems: 1. Your conditional always evaluates `True`, because you can't use `and` like that; and 2. Once you've replaced all of the As with Ts, do you expect replacing all of the Ts with As to ignore then new Ts? – jonrsharpe Sep 22 '15 at 21:41
  • 1
    this could help you [example DNA complementary](http://stackoverflow.com/questions/32685628/converting-letters-using-a-dictionary/32685727#32685727) – Jose Ricardo Bustos M. Sep 22 '15 at 21:54
  • possible duplicate of [Complementary DNA sequence](http://stackoverflow.com/questions/18770650/complementary-dna-sequence) – Jose Ricardo Bustos M. Sep 22 '15 at 21:54
  • @Dungoy Mujahideen Don't forget to accept an answer if someone helped – Kivak Wolf Sep 22 '15 at 21:54
  • 3
    I assume BioPython has a reverse complement function – dkatzel Sep 23 '15 at 02:30
  • Looks like a duplicate. Was already answered here: http://stackoverflow.com/questions/18770650/complementary-dna-sequence/25983565#25983565 – Stefan Gruenwald Mar 28 '17 at 17:50

5 Answers5

3

Another, concise way:

trans_table_AT_CG = str.maketrans({
        'T': 'A',
        'A': 'T',
        'C': 'G',
        'G': 'C'
})
def gene_swap_str(s):
    return s[::-1].translate(trans_table_AT_CG)

So now you can write:

s = input("Enter a string: ").upper()    # Py2: raw_input
print(gene_swap_str(s))

This is a Python 3 answer: in Python 2, str.maketrans can't take a single dict argument, but only two equal-length strings from, to (still supported in Py3). In Py2, you'd use

trans_table_AT_CG = str.maketrans('ATCG', 
                                  'TAGC')    # Py2 and Py3

instead -- this works in Py3 as well, but I find the two parallel strings less clear than the dict. Of course, in Py2, use raw_input not input; in either case, you don't need to wrap the result in str(), as both return strings.

BrianO
  • 1,496
  • 9
  • 12
  • Upvote for ``str.translate`` which is as powerful as forgotten. – Gall Sep 23 '15 at 14:27
  • @Gall -- Thanks, and yes I feel the same, `str.translate`/`str.translate` goes neglected but it's quite a powerhouse. – BrianO Sep 23 '15 at 19:17
  • That is a pretty cool way to do it... I didn't know that existed. – Kivak Wolf Sep 25 '15 at 14:54
  • @Kivak Wolf: Thanks. I felt the methods deserved the publicity. They're remarkable for this and more intricate substitution tasks. [`str.maketrans`](https://docs.python.org/3.4/library/stdtypes.html?highlight=translate#str.maketrans) can create a table from a `dict`, as shown, or from two strings of equal length specifying char-for-char substitution, with an optional third string whose characters will be deleted by `translate`. If you use a `dict`, the replacement strings can be of any length. In short, very versatile & easy to use. (PS -- I upvoted your answer ;) – BrianO 24 mins ago – BrianO Sep 25 '15 at 20:25
  • PPS -- In Python 2, `maketrans` only has part of the interface I described. I updated my answer accordingly. – BrianO Sep 25 '15 at 21:06
2

This is a case where you might consider using a function because it's more portable and reusable in later parts of code. Here is a simple solution to your problem:

def geneSwap(c):
    return {
        'A': 'T',
        'T': 'A',
        'C': 'G',
        'G': 'C',
    }[c]

s = str(raw_input("Enter a string: ")) 
reversed = s[::-1] 

[geneSwap(c) for c in reversed]

print reversed 

However, Python's list processing capabilities allow for much more condensed coding. This uses the geneSwap() function and reverses the sequence all in one line (shiny!):

def geneSwap(c):
    return {
        'A': 'T',
        'T': 'A',
        'C': 'G',
        'G': 'C',
    }[c]

s = str(raw_input("Enter a string: ")) 

print ''.join( [geneSwap(c) for c in s[::-1]] )

** Thanks @BrianO for the correction on the print line.

For those unfamiliar with the code in the print statement in the second code block, the list operation can be broken down into steps from right to left:

  1. s is a string which can be treated as a list of characters. So the list operation [::-1] returns an iterator which increments through the list by increments of -1 from (but not including) the beginning to the beginning (or, from the end to the beginning in reverse order)
  2. [geneSwap(c) for c in s[::-1]] (or you could replace s[::-1] for any list) executes the function on every element c in the list and returns it as a list.
  3. The last part is a ''.join(). You'll notice that step 2 results in a list - not a string. Since the OP wants a string, the last step is to compose a string from the list characters. This is done using the join() string function which joins elements of the passed list using the string the join() is used on. In this case, the OP wants the characters strung together with nothing separating them. So an empty string is used. If the OP wanted spaces or dashes (-) they would use ' '.join() or '-'.join() respectively.

Inspired by Call int() function on every list element?

Community
  • 1
  • 1
Kivak Wolf
  • 830
  • 8
  • 29
  • 1
    You need to join the characters of the list comprehension -- when you print it you get... a list :) In other words, `print ''.join([geneSwap(c) for c in s[::-1]])` – BrianO Sep 22 '15 at 22:01
  • `gene_swap` **blows up** if s contains any characters that are not in "ATCG" -- it'll raise `KeyError`. – BrianO Sep 22 '15 at 22:05
  • yes it does. This is for illustrative purposes only it isn't supposed to account for anything else. If this were a production scenario, there would be many other things to consider. – Kivak Wolf Sep 22 '15 at 22:06
  • If intended for only analyzing gene sequences, it will only ever contain those 4. But I don't want to add all sorts of error checking to code used to illustrate a technique. It just overcomplicates things. – Kivak Wolf Sep 22 '15 at 22:08
  • Um, yes true! I'm thinking too generally. – BrianO Sep 22 '15 at 22:10
1

You can iterate over the string and replace chars as you go.
BTW, this check is not going to work: if "T" and "A" and "G" and "C" in reversed. You can use all() instead.

if all(char in reversed for char in "TAGC"):
    cmap = dict(zip("ATCG", "TAGC"))
    reversed = "".join([cmap[c] for c in reversed])

print(reversed)
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
0

simply iterating over the characters will be cheap timewise:

buffer = ""
for c in string:
    if c == "T":
        buffer += "A"
    elif c == "A":
    ... # etc.
# do as you will with buffer
Aidan Gomez
  • 8,167
  • 5
  • 28
  • 51
0

I think it is more simple in Python 3. e.g.:

def nucleo(dna):
    return dna.translate(str.maketrans("ATCG","TAGC"))
print(nucleo("ACTG"))
Taur
  • 514
  • 3
  • 8