Counting the distance between values with python - python

I am new to python and would be grateful for some help.
I have this script that counts every three bases in a sequence until it identifies a stop codon, then breaks and returns the value. This works for each reading frame 0, +1, +2.
I would like it to return a value of 0 it the script runs to the end of the sequence before identifying a stop codon. At the moment the script returns 18 for count0 which should be 0 as the sequence ends before finding either a "TAG" or a "TAA"
Any help would be gratefully appreciated!
seq="TCATTCTaTTTAAAAAAatATAAAaGGGgTTTTGGGgTTTtGGGGTTTtGGGG"
stop_codons = ["TAG", "TAA"]
count0 = 0
n = 0
while n < len(seq):
if seq[n:n+3] in stop_codons:
break
count0 += 1
n += 3
print count0
count1 = 0
n = 1
while n < len(seq):
if seq[n:n+3] in stop_codons:
break
count1 += 1
n += 3
print count1
count2 = 0
n = 2
while n < len(seq):
if seq[n:n+3] in stop_codons:
break
count2 += 1
n += 3
print count2
Result:
18
3
6

A simple fix would be to do something like this. Nevertheless you should consider refactor your code.
stop_codons = ["TAG", "TAA"]
count0 = 0
n = 0
found = False
while n < len(seq):
if seq[n:n+3] in stop_codons:
found = True
break
count0 += 1
n += 3
if not found:
count0 = 0

I recommend pushing the iterating code into a function:
def get_codon_index(seq, start_idx):
count = 0
n = start_idx
while n < len(seq):
if seq[n:n+3] in stop_codons:
return count
count += 1
n += 3
return -1
This way you save the effort of introducing boolean flags and avoid code duplication.
I return -1 instead of 0, because 0 might be an actual index of a codon (if the codon is right at the beginning of your sequence).

seq="TCATTCTaTTTAAAAAAatATAAAaGGGgTTTTGGGgTTTtGGGGTTTtGGGG"
stop_codons = ["TAG", "TAA"]
def printcount(seq, stop_codons, start):
found = False
count = 0
n = start
while n < len(seq):
if seq[n:n+3] in stop_codons:
found = True
break
count += 1
n += 3
print count if found else 0
printcount(seq, stop_codons, 0)
printcount(seq, stop_codons, 1)
printcount(seq, stop_codons, 2)

You search for the stop codon, and if it finds it, it exits the loop prematurely.
But otherwise, it runs the complete loop, exits the loop when n == len(seq) and then still prints the count.
Two solutions:
Print only when you find a stop codon:
count1 = 0
n = 1
while n < len(seq):
if seq[n:n+3] in stop_codons:
print count1
break
count1 += 1
n += 3
or set a stopped flag:
count1 = 0
n = 1
stopped = False
while n < len(seq):
if seq[n:n+3] in stop_codons:
stopped = True
break
count1 += 1
n += 3
if stopped:
print count1

this code will loop through your sequence and stops when it finds a TAA or TAG sequence returning the position of the first character of the stop codon
seq="TCATTCTaTTTAAAAAAatATAAAaGGGgTTTTGGGgTTTtGGGGTTTtGGGG"
list = ["z", "z", "z"] # otherwise the list will not be of 3 characters
i = 0
for letter in seq:
list.pop(0)
list.append(letter)
codon = "".join(list)
i = i + 1
if codon == "TAG" or codon == "TAA":
print i - 2 # to print the position of T
break

Do yourself a favor and don't re-invent the wheel especially when BioPython is freely available and widely used.

Related

I'm unable to debug this code, not sure what logic i am missing

Given an array of integers arr of even length n and an integer k.
We want to divide the array into exactly n/2 pairs such that the sum of each pair is divisible by k.
Return True If you can find a way to do that or False otherwise.
e.g.
arr = [1,2,3,4,5,10,6,7,8,9], k = 5, output: True
arr = [-1,-1,-1,-1,2,2,-2,-2], k = 3, output: False
The code i've written:
def canArrange(self, arr: List[int], k: int) -> bool:
dictt = {}
for i in range(len(arr)):
arr[i] = arr[i] % k
if arr[i] not in dictt:
dictt[arr[i]] = 1
else:
dictt[arr[i]] += 1
count = 0
for num in arr:
if (k-num) == num:
if dictt[num] > 1:
dictt[num] -= 2
count += 1
else:
dictt[num] -= 1
if (k-num) in dictt and dictt[(k-num)] != 0 and dictt[num] != 0:
dictt[(k-num)] -= 1
dictt[num] -= 1
count += 1
elif num == 0 and dictt[num] > 1:
dictt[num] -= 2
count += 1
if count == len(arr)//2:
return True
else:
return False
My logic is I am first taking the count of "every element % k" and the finding its another pair and reducing the count of both to avoid duplicates, one special case is when the values in a pair are same so for that i am already decrementing the value in my dictionary and at last i am checking whether the number of pairs are equal to half of elements or not
I am able to pass 93/97 test cases on leetcode, and unable to debug for the rest as the length of these 4 test cases are huge hence not possible manually, i must be missing some points while setting my logic, kindly help
Edit: DONE (I have edited the code above)

count an occurrence of a string in a bigger string

I am looking to understand what I can do to make my code to work. Learning this concept will probably unlock a lot in my programming understanding. I am trying to count the number of times the string 'bob' occurs in a larger string. Here is my method:
s='azcbobobegghakl'
for i in range(len(s)):
if (gt[0]+gt[1]+gt[2]) == 'bob':
count += 1
gt.replace(gt[0],'')
else:
gt.replace(gt[0],'')
print count
How do I refer to my string instead of having to work with integers because of using for i in range(len(s))?
Try this:
def number_of_occurrences(needle, haystack, overlap=False):
hlen, nlen = len(haystack), len(needle)
if nlen > hlen:
return 0 # definitely no occurrences
N, i = 0, 0
while i < hlen:
consecutive_matching_chars = 0
for j, ch in enumerate(needle):
if (i + j < hlen) and (haystack[i + j] == ch):
consecutive_matching_chars += 1
else:
break
if consecutive_matching_chars == nlen:
N += 1
# if you don't need overlap, skip 'nlen' characters of 'haystack'
i += (not overlap) * nlen # booleans can be treated as numbers
i += 1
return N
Example usage:
haystack = 'bobobobobobobobobob'
needle = 'bob'
r = number_of_occurrences(needle, haystack)
R = haystack.count(needle)
print(r == R)
thanks. your support help to birth the answer in. here what I have :
numBobs = 0
for i in range(1, len(s)-1):
if s[i-1:i+2] == 'bob':
numBobs += 1
print 'Number of times bob occurs is:', numBobs

Palindrome- while loop instead of for loop

So my program checks for the number of palindrome numbers, lychrels, and non-lychrels. Originally I used a 'break' and a for loop, but I was supposed to use a while loop.
My while loop does not work the same as my for loop and I dont know what i did wrong?
-- The range is meant to be between num1 and num2
also, the output is meant to be an exact copy of the prompt, so thats why it looks like this.
Thanks!
Your while loop:
while (nums>=num1 and nums<=num2 and flag):
#for nums in range(num1, num2+1):
num_str = str(nums)
if num_str == num_str[::-1]:
pal += 1
else:
count = 0
num_el = num_str
while (count < 60):
np_total = int(num_el) + int(num_el [::-1])
count += 1
nums_el = str(np_total)
num_el = nums_el
if num_el == nums_el [::-1]:
nonlych += 1
flag = False
else:
lychrel += 1
print(nums, "looks like a lychrel number")
nums += 1
The
else:
lychrel += 1
print(nums, "looks like a lychrel number")
is executing every time the while loops exits. The break in your for loop was skipping it.
Second problem is that when flag is set to False, it will stop your outer while loop, so the first non-lychrel number you find will be the last number you test.
Here's my attempt at changing as little as possible. You can add a flag like isLychrel instead of using the count variable to pass information.
nums = num1
while (nums>=num1 and nums<=num2):
num_str = str(nums)
if num_str == num_str[::-1]:
pal += 1
else:
count = 0
num_el = num_str
while (count < 60):
np_total = int(num_el) + int(num_el [::-1])
count += 1
nums_el = str(np_total)
num_el = nums_el
if num_el == nums_el [::-1]:
nonlych += 1
count = 999 # breaks while loop
if (count != 999):
lychrel += 1
print(nums, "looks like a lychrel number")
nums += 1

Python - variable not updating in loop

I am trying to solve the 'Love-Letter' mystery problem of HackerRank using Python, but I am stuck at a place where in my loop a variable is not getting updated.
s = input()
first_char = s[0]
last_char = s[-1]
ascii_first_char = ord(first_char)
ascii_last_char = ord(last_char)
count = 0
i = 1
while ascii_first_char < ascii_last_char:
count += abs((ascii_last_char-ascii_first_char))
ascii_first_char = ord(s[i])
ascii_last_char = ord(s[-i])
i += 1
print(count)
If you try to run that, you would see that alc is not changing it's value according to ord(s[i]) where I keeps incrementing. Why is that happening?
You get the first letter with s[0] and the last with s[-1]. In your loop you take the next letters with the same index i.
I don't understand your condition in the while loop. Instead of "ascii_first_char < ascii_last_char" you should test if you have looked at every element of the string. For that we have to loop len(s)/2 times. Something like:
while i < len(s) - i:
or equivalent
while 2*i < len(s):
And this conditions only work for even length. I prefer for-loops when I know how many times I will loop
current_line = input()
# if length is even, we don't care about the letter in the middle
# abcde <-- just need to look for first and last 2 values
# 5 // 2 == 2
half_length = len(current_line) // 2
changes = 0
for i in range(index):
changes += abs(
ord(current_line[i]) - ord(current_line[-(i+1)])
)
print (changes)
s1 = ['abc','abcba','abcd','cba']
for s in s1:
count = 0
i = 0
j = -1
median = len(s)/2
if median == 1:
count += abs(ord(s[0])-ord(s[-1]))
else:
while i < len(s)/2:
count += abs(ord(s[j])-ord(s[i]))
i += 1
j -= 1
print(count)

How to replace the for with a while loop

How can I change the for loop into a while loop. What are the significant differences between using for and while loop?
S="I had a cat named amanda when I was little"
count = 0
for i in S:
if i =="a":
count += 1
print (count)
Following is the while loop implementation of same code.
i = 0
count = 0
while i < len(S):
if S[i] == 'a':
count += 1
i += 1
print count
You need a counter which will be incremented each time "while counter < len(S)"
Here's a start:
index = 0
count = 0
while index < len(S):
#do something with index and S ...
index += 1
You could also do it via the boolean nature of an empty string/list/dictionary.
S="I had a cat named amanda when I was little"
count = 0
while S:
# pop the first character off of the string
ch, S = S[0], S[1:]
if ch == "a":
count += 1
print (count)

Categories

Resources