Can't get this break statement to work [duplicate] - python

This question already has answers here:
How can I break out of multiple loops?
(39 answers)
Closed 5 years ago.
I want to find the highest number not in the list. The break should end the last for loop and leave me with Ans = highest number not in list. Why doesn't it work
A = [1,3,5,9,11]
u = A[0]
for i in range(1, len(A)):
if A[i] > u:
u = A[i]
if u <= 0:
Ans = 1
else:
for j in range(u ,0, -1):
if j not in A:
Ans = j
print(Ans)
break

break gets you out of the inner loop, you also need to exit the outer one. You could do this using a boolean flag, etc... but I prefer using a for - else construct
for-else, means no break, that is the loop will resume in the else attached to the for when there is no break in the inner loop, otherwise, it will execute the following.
continue, takes you to the end of the loop.
Now, it seems your logic may also have a problem, the answer printed is 2
A = [1,3,5,9,11]
u = A[0]
for i in range(1, len(A)):
if A[i] > u:
u = A[i]
if u <= 0:
Ans = 1
else:
for j in range(u ,0, -1):
if j not in A:
Ans = j
print(Ans)
break
else: # <-- attention, this "else" must be aligned with the preceding "for", not the "if"
continue
break

As already mentioned, the break works fine, breaking from the loop it is in -- but not from the loop above that!
Alternatively to using for/else or moving the entire calculation into a function and using return instead of break, you could also replace the nested loop with a generator, lazily finding the next value that satisfies the condition. If that value is not None (the default), break from the outer loop.
else:
r = next((j for j in range(u ,0, -1) if j not in A), None)
if r is not None:
Ans = r
print(Ans)
break

# foo bar et al.
Seems the indentation was wrong as per your suggestions. While all your other suggestions were more elegant my solution turned out to be:
A = [1,3,5,9,11]
u = A[0]
for i in range(1, len(A)):
if A[i] > u:
u = A[i]
if u <= 0:
Ans = 1
print(Ans)
else:
for j in range(u ,0, -1):
if j not in A:
Ans = j
print(Ans)
break

Your break doesn't work, because your indentation for if u <= 0: and further is wrong.
A = [-1, -3, -5, -9, -11]
Ans = 1
for j in range(max(A)-1, max(0, min(A)), -1):
if j not in A:
Ans = j
print(Ans)
break
However, I advise you to use NumPy if your list is huge, because it is much faster.
# Find the highest number not in the list
import numpy as np
l = [1,3,5,9,11]
a = np.array(l)
ans = 1
for i in range(a.max()-1, max(0, a.min()), -1):
if i not in a:
ans = i
print(i)
break

Related

Number of inversions with merge sort: Why do I not need to initialize a global variable here?

I implemented merge sort in python and am trying to get the number of inversions of a given array. An inversion is defined as a pair of indices 0 ≤ 𝑖 < 𝑗 < 𝑛 such that 𝑎𝑖 > 𝑎𝑗. This problem is also described as 'how far away is an array from being sorted'.
Here is my code:
def merge(a,b):
c = [] # Output array
i, j = 0, 0 # Indices of the left and right split arrays
global num_inversions
# It looks like there is no need to initialize this? I don't understand this
while i < len(a) and j < len(b):
if a[i] <= b[j]:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
num_inversions = num_inversions + len(a) - i
if i == len(a):
c.extend(b[j:])
else:
c.extend(a[i:])
return c
def mergesort(a):
# Base case
if len(a) <= 1:
return a
mid = len(a) // 2
left_array = mergesort(a[:mid])
right_array = mergesort(a[mid:])
return merge(left_array, right_array)
if __name__ == '__main__':
#inp = input()
#n, *a = list(map(int, inp.split()))
a = [6, 5, 4, 3, 2, 1] # Sample input. Gives the correct answer 15
a_sorted = mergesort(a)
print(num_inversions)
I seem to be getting the correct result. What I don't understand is why the global variable num_inversions can be declared in the function, and why it doesn't need to be initialized.
Initializing it in the function is obviously wrong because the value will keep getting rewritten each time the function is called recursively.
Edit: Sorry, this question was incredibly stupid. I realized I did initialize it at some point while testing it, and forgot.

How do I close the loop?

I am given an array of n numbers [a0,a1, a2, …, an-1] and I am supposed to write a function named sumOfThree that takes in the array and a number K as the only 2 arguments and outputs the number of unique unordered triplets in the array that sum to K. This is my code:
def sumOfArray(arr,K):
arr.sort()
s=set()
for i in range(len(arr)-2):
j=i+1
k=len(arr)-1
while j<k:
if arr[i]+arr[j]+arr[k]==K:
s.add((arr[i],arr[j],arr[k]))
elif arr[i]+arr[j]+arr[k]<K:
j+=1
else:
k-=1
return len(s)
However I am unable to find the answer. Any help please?
Just as MZ mentioned,
when arr[i]+arr[j]+arr[k]==K, the i,j,k never changed.
However, if you just add a single break as cewaphi mentioned, the while loop will stop at first match for every i loop, instead of walking through all the combinations.
Here is another way to solve the problem:
def sumOfArray(arr, K):
arr.sort()
s = set()
count = 0
for i in range(len(arr) - 2):
for j in range(i+1,len(arr)-1):
for k in range(j+1,len(arr)):
if arr[i] + arr[j] + arr[k] == K:
s.add((arr[i], arr[j], arr[k]))
print('Done')
length = print('length: ' + str(len(s)))
return length
As MZ stated, you are stuck in your if condition.
Either increment j or decrement k so that the condition j < k is met.
Or if you are done with increment i and want to continue with i+1, simply add a break:
if arr[i]+arr[j]+arr[k]==K:
s.add((arr[i],arr[j],arr[k]))
break

How to break while loop

I am trying to find if a element in a list exists in a range where the list size is known and number of ranges is also known
I have tried a logic in python using a while loop
a[1]=[23,330,460]
r=[1,120,300,450,600]
and my range list are
1 to 100 for i=0
120 to 220 for i=1
300 to 400 for i=2
450 to 550 for i=3
600 t0 700 for i=4
a[1] has some values which is compared with the elements in range
a[0] is output got after checking
if a[1] is not in the range defined
a[0] must be 0,
else 1
j=0
for i in range(0,5):
while j<3:
l=list(range(r[i],r[i]+100))
if a[1][j] in l:
a[0].append(1)
j=j+1
else:
a[0].append(0)
j=j
I expect the output to be a[0]=[1 0 1 1 0]
Your code does not change 'j' value in else since it executes first in this case,so it becomes infinite.
a=[[],[23,330,460]]
r=[1,120,300,450,600]
for i in range(5):
j=0
l=list(range(r[i],r[i]+100))
while j<3:
if a[1][j] in l:
a[0].append(1)
break
j=j+1
else:
a[0].append(0)
print(a[0])
#[1, 0, 1, 1, 0]
Using for
a=[[],[23,330,460]]
r=[1,120,300,450,600]
for i in range(5):
l=list(range(r[i],r[i]+100))
for j in a[1]:
if j in l:
a[0].append(1)
break
else:
a[0].append(0)
print(a[0])
#[1, 0, 1, 1, 0]
Using any
Updated as per tripleee answer, range is not necessary
a=[[],[23,330,460]]
r=[1,120,300,450,600]
for i in range(5):
a[0].append(int(any(r[i]<=j<=r[i]+100 for j in a[1])))
print(a[0])
#[1, 0, 1, 1, 0]
What about if you use another if: if the result is what you expect, keep going. If not, break.
result = []
for pos, val in enumerate(a[1]):
if r[pos] <= val <= r[pos]+100:
comp = 1
else:
if comp == 1 then
echo 'Well done'
else break 0;
result.append(comp)
Not pretty sure btw...
Creating a list of 100 elements on each iteration over the loop is extremely inefficient and unidiomatic. I think you want simply
result = []
for pos, val in enumerate(a[1]):
if r[pos] <= val <= r[pos]+100:
comp = 1
else:
comp = 0
result.append(comp)
or more succinctly with a list comprehension
result = [1 if r[pos] <= val <= r[pos]+100 else 0
for pos, val in enumerate(a[1])]
If you want the value to be in a[0] then simply assign a[0] = result at the end; but really, this design is extremely dubious. I would suggest you keep two separate variables, or possibly refactor the input and output into a class if you need to keep them together.

return in python error only returns one value

I am having some trouble with the return. I want to add numbers produced from the function to a list already created but when I return, I just get one value, but if I use print it is fine.
Does the return only produce one value?
def aFunction(n):
for j in range(2,n):
for i in range(2,j):
if (j % i ==0):
break
else:
return(j)
break
print(aFunction(10))
Ok so this time i have edited the code slightly, how can i use p to divide n(which is an int)so that if no remainder remains i can append it to p?
def function(n):
p = [2,]
for j in range(3,n):
if (j // p) == 0:
p.append(j)
return(p)
print(function(20))
Because return terminate the function, so when condition goes to else clause, it terminate the functions,
Use generators:-
def aFunction(n):
for j in range(2,n):
for i in range(2,j):
if j % i == 0:
break
else:
yield j
break
print list(aFunction(10))
Because return terminates the function and returns the value.
You should add these values to a list and then print the list:
def aFunction(n):
l = []
for j in range(2,n):
i in range(2,j):
if (j % i != 0):
l.append(j)
return l
print(aFunction(10))
In Python, you can write a better code:
[j for j in range(2,n) for i in range(2,j) if j % i != 0]

Implementing Insertion Sort in Python with For Loops only

I tried implementing Insertion sort with for loops only and wrote the following code:
def isort(L): #implementation with a for loop
for i in range(1,len(L)):
small = L[i]
M = range(i)
M.reverse()
for j in M:
if small<L[j]:
L[j+1]=L[j]
else:
break
L[j+1] = small
return L
L = [5,4,3,2,1]
M = isort(L)
print M
This gives the output [5,1,2,3,4]. Can someone please point out where I am making a mistake
Change (the fix shown in the question is easy, the one-off error was caused by one little +1 :)):
L[j+1] = small
To:
L[j] = small
Testing:
>>> isort([5, 4, 3, 2, 1])
[1, 2, 3, 4, 5]
However, there are some other things with your code, as illustrated- it will not work alot of the time. With a fair few tweaks, we can get it to work:
def isort(L):
for i in range(1,len(L)):
small = L[i]
M = range(-1, i)
M.reverse()
for j in M:
if j>=0 and small<L[j]:
L[j+1]=L[j]
else:
break
L[j+1] = small
return L
Testing:
>>> isort([4, 5, 3, 2, 1])
[1, 2, 3, 4, 5]
The post condition for the inner loop is that j is pointing for the first value that is smaller than small (this is achieved by the break call). However, the loop naturally exists when j=0, therefore in every last inner iteration, the condition is not what you'd expect.
To fix it, I suggest initializing M from -1:
M = range(-1, i)
But then, you have to check as well that j is positive (to avoid making changes you don't want to):
if j>=0 and small<L[j]:
L[j+1]=L[j]
This is little tricky :
I took the inner loop range function as range(j, -2, -1) , so the inner loop always breaks at one position ahead, so the last statement arr[j + 1] = key works perfectly
arr = [5, 4, 3, 2, 1]
for i in range(1, len(arr)):
j = i - 1
key = arr[i]
for j in range(j, -2, -1):
if j < 0 or key >= arr[j]:
break
else:
arr[j + 1] = arr[j]
arr[j + 1] = key
if __name__ == "__main__":
n = int(input("How many numbers ?\t"))
nums = [int(x) for x in input("Enter {} numbers\t".format(n)).split()]
for i in range(1,n):
val = nums[i]
for j in range(i-1,-2,-1):
if j < 0 : break
if nums[j] > val:
nums[j+1] = nums[j]
else:
break
nums[j+1] = val
for num in nums:
print(num,end=' ')
print()

Categories