my_data = [4, 8, 15, 16, 23, 42]
index = 0
for item in my_data:
k = 0
for i in range(2, item+1):
if (i % 2 == 0):
k += 1
my_data[index] = k
index += 1
print(my_data)
The above code takes all the elements of the given list and divides them by 2, and it works all fine, however I was trying to convert it into while loop for sake of practice,but for some reason I am getting no error, but the code keeps running and I had to force stop it.
i = 0
while i < len(my_data):
j = 2
while j < i+1:
if j % 2 == 0:
j += 1
my_data[i] = j
i += 1
print my_data
And here is the method I have tried to implement which seems to not work as far as I am concerned. If someone could clarify it for me I would appreciate it. Thank you in advance.
your second while loop moves forward only if j is pair and if j is not (since j increase only by 1) the while loop will loop for ever.
you've made a little mistake by replacing k with j, and you should continue using k
i = 0
while i < len(my_data):
j = 2
k = 0
while j < i+1:
if j % 2 == 0:
k+=1
j += 1
my_data[i] = k
i += 1
print my_data
At line 5:
if j % 2 == 0:
When i==3 and j==3, the if statement is ignored. j can't be increased. It will be looped forever, since the stop criterion is j<i+1
Just add an else statement to handle that case
If you are just trying to divide each item of a list using while you also try this way.
my_data = [4, 8, 15, 16, 23, 42]
index = 0
while len(my_data) > index:
my_data[index] = int(my_data[index]/2)
index +=1
print(my_data)
Related
I wanted to write a program that will show the number of combinations of the number 196225 but I failed because it showed very strange numbers and I can't quite understand why
my code:
list = []
liczba = [1,9,6,2,2,5]
n_num = 0
iter=0
#ijlkmn
for i in range(6):
n_num = liczba[i]*10**5
for j in range(6):
if j != i:
n_num += liczba[j]*10**4
for l in range(6):
if l != i and l != j:
n_num += liczba[l]*10**3
for k in range(6):
if k != i and k != j and k!= l:
n_num += liczba[k]*10**2
for m in range(6):
if m != i and m != j and m != l and m!= k:
n_num += liczba[m]*10
for n in range(6):
if n != i and n != j and n != l and n!= k and n!= m:
n_num += liczba[n]
if (n_num in list) == False:
list.append(n_num)
iter += 1
I know it looks very primitive but I only wanted the result which turned out to be incorrect, here are some of its numbers ~
196225, 196277, 196502, 196554, 197076, 197098, 199723, 199775, 200040
could someone tell me where did these numbers come from?
if you want to make all the possible numbers using tose digits , you can use itertools module :
import itertools
liczba = [1, 9, 6, 2, 2, 5]
numbers = itertools.permutations(liczba, 6)
for num in numbers:
print(num)
You are adding to previous answers on each of your internal loops. Because the value of n_num is not reset at each iteration. For example:
digits = [1,2,3]
for k in range(3):
n_num = digits[k]*10**2
for k2 in range(3):
if k2!=k:
n_num += digits[k2]*10
print(n_num)
prints
120
150
210
240
310
330
because when k2 = 2 the first time, 30 is added to 120 yielding 150... etc etc
I see what's wrong with your code - let's look into smaller example to see it clearly and find a solution
liczba = [1, 2, 3]
for i in range(3):
n_num = liczba[i] * 10 ** 2 # it start with 1 * 100 = 100, good one!
for j in range(3):
if j != i: # for j = 0 it just pass
n_num += liczba[j] * 10 # j = 1, n_num is now 100 + 20 = 120
for l in range(3):
if l != i and l != j: we skip 0 and 1
n_num += liczba[l] # n_num = 123, great
list.append(n_num)
Now we back to second loop:
for j in range(3): # j jumps to 2
if j != i:
n_num += liczba[j] * 10 # wait - here is the problem, our n_num should be 100 here again but now it's 123, so we add 30 to previous solution
for l in range(3):
if l != i and l != j: # l = 1
n_num += liczba[l] # adding 2, but instead of 100 + 30 + 2 we have 123 + 30 + 2
list.append(n_num)
How to fix it? Very simple - you can just calculate number once at the end. You have all indexes already, so write
n_num = liczba[i] * 10 ** 5 + liczba[j] * 10 ** 4 + ...
And one small hint for the end - if you use set instead of list you won't need a check if n_num is already in result.
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.
Im trying to implement merge sort in python and I'd like to know what is the pythonic way of looping through two lists iterating only one of the lists each loop.
This is what I have now (using indexes)
def merge(array1, array2):
final = []
i = 0
j = 0
while i < len(array1) or j < len(array2):
if array1[i] <= array2[j]:
final.append(array1[i])
i += 1
elif array2[j] < array1[i]:
final.append(array2[j])
j += 1
# Finished one of the arrays
if i == len(array1):
final.extend(array2[j:])
break
elif j == len(array2):
final.extend(array1[i:])
break
return final
Thanks.
I'm not sure not sure your problem here is using indices, but there's a lot of unneeded code.
Firstly, we can change your initialisers to:
final, i, j = [], 0, 0
Next, if we change your while condition we can remove the breaks:
while i < len(array1) and j < len(array2):
Your elif isn't meaningful as it will always be true, we can thus make your if:
if array1[i] <= array2[j]:
final.append(array1[i])
i += 1
else:
final.append(array2[j])
j += 1
And now because we're automatically breaking out of the loop we don't need the breaks and can move the extends outside:
def merge(array1, array2):
final, i, j = [], 0, 0
while i < len(array1) and j < len(array2):
if array1[i] <= array2[j]:
final.append(array1[i])
i += 1
else:
final.append(array2[j])
j += 1
final.extend(array1[i:])
final.extend(array2[j:])
return final
This gives you smaller, more readable code without actually changing the way you're doing anything, that way you'll still understand it.
Note that we can perform:
final.extend(array1[i:])
final.extend(array2[j:])
outside the loop because one array will have contents, for example [7,9], while the other will be empty([]):
>>> final = [3,6]
>>> array1 = [3,6]
>>> array2 = [7,9]
>>> i = 2
>>> j = 0
>>> array1[i:]
[]
>>> array2[j:]
[7, 9]
>>> final.extend(array1[i:])
>>> final
[3, 6]
>>> final.extend(array2[j:])
>>> final
[3, 6, 7, 9]
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()
I am trying to implement the merge sort algorithm described in these notes by Jeff Erickson on page 3. but even though the algorithm is correct and my implementation seems correct, I am getting the input list as output without any change. Can someone point out the anomalies, if any, in it.
def merge(appnd_lst, m):
result = []
n = len(appnd_lst)
i, j = 0, m
for k in range(0, n):
if j < n:
result.append(appnd_lst[i])
i += 1
elif i > m:
result.append(appnd_lst[j])
j += 1
elif appnd_lst[i] < appnd_lst[j]:
result.append(appnd_lst[i])
i += 1
else:
result.append(appnd_lst[j])
j += 1
return result
def mergesort(lst):
n = len(lst)
if n > 1:
m = int(n / 2)
left = mergesort(lst[:m])
right = mergesort(lst[m:])
appnd_lst = left
appnd_lst.extend(right)
return merge(appnd_lst, m)
else:
return lst
if __name__ == "__main__":
print mergesort([3, 4, 8, 0, 6, 7, 4, 2, 1, 9, 4, 5])
There are three errors in your merge function a couple of indexing errors and using the wrong comparison operator. Remember python list indices go from 0 .. len(list)-1.
* ...
6 if j > n-1: # operator wrong and off by 1
* ...
9 elif i > m-1: # off by 1
* ...