I am given a string and have to return False if there is one or more invalid characters, otherwise True. The caveat is that I can only built-in functions and str operations (for example: in, +, indexing, len) and recursion. What I have so far is not working:
def is_valid_sequence(dna):
""" (str) -> bool
Return True if and only if the DNA sequence is valid
(A, T, C, and G)
:param dna: string sequence
:return: true or false
>>> is_valid_sequence('ATTAC')
True
>>> is_valid_sequence('FBSSS')
False
"""
valid_seq = 0
if len(dna) == 1 and dna in ['A', 'T', 'C', 'G']:
valid_seq += 1
else:
return is_valid_sequence(dna[1:])
Obviously, this code doesn't work because of recursion and adding 1 to the valid_seq
variable just gets wiped after the next recursive iteration.
For DNA sequences of a small size (around a thousand characters), this is a practical implementation
A word of caution
Be careful with recursion in python tho – a long
dna
string will cause a stack overflow. Attempting to validate even a sequence this "large" would failYou can easily avoid this by implementing
is_valid_sequence
using a Clojure-styleloop
/recur
mechanism for constant-space recursionContinued improvements
The
loop
/recur
implementation exposes an additional opportunity to tune the performance of our function. Slicing the string as we have done withdna[0]
anddna[1:]
creates new strings in memory; this was only necessary because of the recursion API used in the first function we wroteThe
loop
/recur
interface allows us to use whatever data type is suitable for computing our output – in this case, a simple integer index will do. Lexical scoping takes care of the rest –dna
is accessible within our lambda and does not need to dodna[1:]
slicing which will save a lot of time/space for large inputsPython and the Unruly Lambda
Notice how we were forced to use a pure expression inside the lambda instead of the traditional
if/elif/else
statement syntax – this is not a problem for simple programs, but more complex programs might be difficult to express this way in python.This works identically to the program above but uses a plain old function instead of a lambda