How Nested For loop works - python

def SNP(seq1, seq2):
result = []
counter = 0
for position, base in enumerate(seq1):
for position2, base2 in enumerate(seq2):
if base != base2:
result.append(position)
result.append(base)
result.append(base2)
counter += 1
if counter == 2:
return None
result2 = tuple(result)
return result2
print(SNP('AAGCCTA', 'AAGCTTA'))
If the "if statement" is invalid, the loop starts again with the 2nd for loop which I did not intend to...
So the question is after the if statement, how should I let the code start again with the first loop instead of 2nd for loop after 1 loop?

def SNP(seq1, seq2):
result = []
counter = 0
for position, base in enumerate(seq1):
for position2, base2 in enumerate(seq2):
if base != base2:
result.append(position)
result.append(base)
result.append(base2)
counter += 1
if counter == 2:
break
result2 = tuple(result)
return result2
Added the break to the if. Sorry if that's the wrong if statement.

You simply neead a break in the if block, like this
if base != base2:
result.append(position)
result.append(base)
result.append(base2)
counter += 1
if counter == 2:
return None
else:
break

Related

finding the longest common prefix of elements inside a list

I have a sequence print(lcp(["flower","flow","flight", "dog"])) which should return fl. Currently I can get it to return flowfl.
I can locate the instances where o or w should be removed, and tried different approaches to remove them. However they seem to hit syntax issue, which I cannot seem to resolve by myself.
I would very much appreciate a little guidance to either have the tools to remedy this issue my self, or learn from a working proposed solution.
def lcp(strs):
if not isinstance(strs, list) or len(strs) == 0:
return ""
if len(strs) == 1:
return strs[0]
original = strs[0]
original_max = len(original)
result = ""
for _, word in enumerate(strs[1:],1):
current_max = len(word)
i = 0
while i < current_max and i < original_max:
copy = "".join(result)
if len(copy) and copy[i-1] not in word:
# result = result.replace(copy[i-1], "")
# result = copy[:i-1]
print(copy[i-1], copy, result.index(copy[i-1]), i, word)
if word[i] == original[i]:
result += word[i]
i += 1
return result
print(lcp(["flower","flow","flight", "dog"])) # returns flowfl should be fl
print(lcp(["dog","car"])) # works
print(lcp(["dog","racecar","car"])) # works
print(lcp([])) # works
print(lcp(["one"])) # works
I worked on an alternative which does not be solve removing inside the same loop, adding a counter at the end. However my instincts suggest it can be solved within the for and while loops without increasing code bloat.
if len(result) > 1:
counter = {char: result.count(char) for char in result}
print(counter)
I have solved this using the below approach.
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
N = len(strs)
if N == 1:
return strs[0]
len_of_small_str, small_str = self.get_min_str(strs)
ans = ""
for i in range(len_of_small_str):
ch = small_str[i]
is_qualified = True
for j in range(N):
if strs[j][i] != ch:
is_qualified = False
break
if is_qualified:
ans += ch
else:
break
return ans
def get_min_str(self, A):
min_len = len(A[0])
s = A[0]
for i in range(1, len(A)):
if len(A[i]) < min_len:
min_len = len(A[i])
s = A[i]
return min_len, s
Returns the longest prefix that the set of words have in common.
def lcp(strs):
if len(strs) == 0:
return ""
result = strs[0]
for word in strs[1:]:
for i, (l1, l2) in enumerate(zip(result, word)):
if l1 != l2:
result = result[:i]
break
else:
result = result[:i+1]
return result
Results:
>>> print(lcp(["flower","flow","flight"]))
fl
>>> print(lcp(["flower","flow","flight", "dog"]))
>>> print(lcp(["dog","car"]))
>>> print(lcp(["dog","racecar","car"]))
>>> print(lcp([]))
>>> print(lcp(["one"]))
one
>>> print(lcp(["one", "one"]))
one
You might need to rephrase your goal.
By your description you don't want the longest common prefix, but the prefix that the most words have in common with the first one.
One of your issues is that your tests only test one real case and four edgecases. Make some more real examples.
Here's my proposition: I mostly added the elif to check if we already have a difference on the first letter to then discard the entry.
It also overwrites the original to rebuild the string based on the common prefix with the next word (if there are any)
def lcp(strs):
if not isinstance(strs, list) or len(strs) == 0:
return ""
if len(strs) == 1:
return strs[0]
original = strs[0]
result = ""
for word in strs[1:]:
i = 0
while i < len(word) and i < len(original) :
if word[i] == original[i]:
result += word[i]
elif i == 0:
result = original
break
i += 1
original = result
result = ""
return original
print(lcp(["flower","flow","flight", "dog"])) # fl
print(lcp(["shift", "shill", "hunter", "shame"])) # sh
print(lcp(["dog","car"])) # dog
print(lcp(["dog","racecar","car"])) # dog
print(lcp(["dog","racecar","dodge"])) # do
print(lcp([])) # [nothing]
print(lcp(["one"])) # one

run code after yield statement in python generator when using break

I have a simple generator:
def counter(n):
counter = 0
while counter <= n:
counter += 1
yield counter
print(f"Nice! You counted to {counter}")
def test_counter():
for count in counter(6):
print(f"count={count}")
if count > 3:
break
In this example there is a break once count reaches 3. However the only problem with the code is that the break terminates the generator execution at the yield statement. It doesn't run the print statement after the yield statement. Is there a way to execute code within the generator that is after the yield statement when a break occurs?
Example run:
# What happens:
>>> test_counter()
count=1
count=2
count=3
count=4
# What I'd like to see:
>>> test_counter()
count=1
count=2
count=3
count=4
Nice! You counted to 4
You have to put the print in a finally-block:
def counter(n):
try:
counter = 0
while counter <= n:
counter += 1
yield counter
finally:
print(f"Nice! You counted to {counter}")
def test_counter():
for count in counter(6):
print(f"count={count}")
if count > 3:
break
You can use send method of generator:
def counter(n):
counter = 0
while counter <= n:
counter += 1
should_continue = yield counter
if should_continue == False:
break
print(f"Nice! You counted to {counter}")
def test_counter():
gen = counter(6)
for count in gen:
print(f"count={count}")
if count > 3:
try:
gen.send(False)
except StopIteration:
break
Now test_counter() works as expected.

Annotating adjacent values in a list

It's supposed to be a roll of dice (random) then adjacent values (runs) are supposed to be in ( ). One challenge is using the current - 1 with the 0 index (think I got that resolved by using range(len(dieRun) -1). But another challenge is using 'current + 1' as it tends to 'out of range' errors.
One thought I have is to maybe build a function to compare the values for adjacents? Then use whatever return I get from that to reference a variable, then use that variable in a formatted Print of the dieRun? But, I don't see how that would be better as then I'd still have to figure out how to place that variable as a "(" or ")" with the print(dieRun) list.
Still a newb.
def main():
from random import randint
counter = 0
inRun = 0
dieRun = []
while counter < 20:
roll = randint(0,6)
dieRun.append(roll)
counter = counter +1
index = 0
counter = 0
value = 0
inRun == False
print(dieRun) # just to see what I'm working with
while counter < len(dieRun):
for i in range(0, len(dieRun)-1):
if dieRun[i] != dieRun[i-1]:
print(")" , end= "")
inRun = False
counter = counter + 1
if dieRun[i] == dieRun[i+1]:
inRun = True
print("(")
counter = counter + 1
print(dieRun[i])
if inRun:
print("(")
if inRun :
print(")", end="")
main()
if you want the output like: 1(3 3) 4 5 (6 6 6) 2 1 3 (2 2) 1 (4 4) 5 6 1 2
from random import randint
dieRun = []
for i in range(20):
roll = randint(0,6)
dieRun.append(roll)
inRun = False
print(dieRun)
for i, n in enumerate(dieRun):
if i < len(dieRun)-1:
if not inRun:
if n == dieRun[i+1]:
print('(', n,' ', end='')
inRun = True
else:
print(n,' ', end='')
else:
if n != dieRun[i+1]:
print(n, ')',' ', end='')
inRun = False
else:
print(n,' ', end='')
else:
if dieRun[i-1] == n:
print(n, ')')
else:
print(n)
just a thought, hope it help.
Just a quick fix, I have commented in the code.
For the inline print, you have provided the solution 'print(")" , end= "")', but I don't know why you didn't make it for every print().
if dieRun[i] != dieRun[i-1]: # will check the first number with last number
dieRun[0] != dieRun[-1]: # [-1] is the last item in the list
if dieRun[i] == dieRun[i+1]: # will index out of length
dieRun[len(..)-1] != dieRun[len(..)]: # [len(..)] wil be out of range
Since the head and tail of the list will always cause problem, I just chopped them off from the for loop, and do it manually.
There must be some cleaner solution:
from random import randint
counter = 0
inRun = 0
dieRun = []
while counter < 20:
roll = randint(0,6)
dieRun.append(roll)
counter = counter +1
index = 0
counter = 0
value = 0
inRun == False
print(dieRun)
# while counter < len(dieRun): # while loop is redundant with the for loop
print('(', dieRun[0],' ', end='') # print the first number manually
for i in range(1, len(dieRun)-1):
if dieRun[i] != dieRun[i-1]:
print(")(" , end= "") # change ")" to ")("
inRun = False
counter = counter + 1
"""
these are redundant, just like if True, don't need elif not True
# if dieRun[i] == dieRun[i+1]:
# inRun == True
# print("(", end='')
# counter = counter + 1
"""
print(dieRun[i],' ', end='')
print(dieRun[-1],')', end='') # print the last number manually

Resetting Collatz Counter on Each New Recursion

I made a code that measure number of steps it takes to return to 1 in a Collatz Conjecture. Here Is my code
counter = 0
def collatz(n):
global counter
counter += 1
if n <= 0 :
return "Invalid Number"
elif n == 1 :
return counter
elif n % 2 == 1 :
n = 3*n + 1
return collatz(n)
elif n % 2 == 0 :
n = n/2
return collatz(n)
print(collatz(9921615699))
print(collatz(9921615699))
I expect the Last two print commands to print 311 and 311. Instead, they print 311 and 622. I guess that was easy enough to see in the code what is wrong. How can i fix that? how can counter reset each time a command is completed and not when the function is run.
Instead of using global variable you could make the counter a parameter with default value:
def collatz(n, counter=0):
counter += 1
if n <= 0 :
return "Invalid Number"
elif n == 1 :
return counter
elif n % 2 == 1 :
n = 3*n + 1
return collatz(n, counter)
elif n % 2 == 0 :
n = n/2
return collatz(n, counter)
You're using recursion, so just use it properly:
def collatz(n, counter=0):
counter += 1
if n <= 0 :
return "Invalid Number"
elif n == 1 :
return counter
elif n % 2 == 1 :
n = 3*n + 1
return collatz(n, counter)
elif n % 2 == 0 :
n = n/2
return collatz(n, counter)
print(collatz(9921615699))
print(collatz(9921615699))
You were using global in your original version which is usually not what you want to do. You got to see first-hand why.
You could have reset the counter, e.g.
result = counter
counter = 0
return result
But that's pretty nasty, let's not do that. When you're implementing a recursive algorithm there's probably no good reason to have a global variable.

How to count cycles and print it

I have a programm, which uses binary search.
And in the end, i need to print a count of loops.
How it would be better to do?
import re
def binarySearch(sumList, whattofind):
a=0
if len(sumList) == 0:
return False
else:
midpoint = len(sumList)/2
if sumList[midpoint]==whattofind:
a=a+1
print(a)
return True
else:
if whattofind<sumList[midpoint]:
a+=1
return binarySearch(sumList[:midpoint],whattofind)
else:
a+=1
return binarySearch(sumList[midpoint+1:],whattofind)
print(a)
result = re.findall(r'\w\w', open("text.txt","r").read())
sumList=[]
for line in result:
sumList.append(ord(line[0])+ord(line[1]))
sumList.sort()
whattofind=int(input('Enter number: '))
print (sumList)
print(binarySearch(sumList, whattofind))
do the following
count = 0
def binarySearch(sumList, whattofind):
global count
count += 1
and at the last line of code just print value of count

Categories

Resources