Python : iterating over a list - python

With my code I would except that after looping one time he will jump to the next number in the list, but he doesn't. Anyone knows what is wrong with my code?
for j in range(len(k)):
s = [int(i) for i in str(k[j])]
This two lines of code are part of a bigger question I am solving.
def kaprekarseries(n):
"""
>>> kaprekar_series(677)
[677, 99, 0]
>>> kaprekar_series(9876)
[9876, 3087, 8352, 6174]
>>> kaprekar_series(55500)
[55500, 54945, 50985, 92961, 86922, 75933, 63954, 61974, 82962]
"""
k = list()
k.append(n)
count = 0
while count < 10:
for j in range(len(k)):
s = [int(i) for i in str(k[j])]
m = sorted(s, key=int, reverse=True)
m2 = int(''.join(str(i) for i in m))
l = sorted(s, key=int)
l2 = int(''.join(str(i) for i in l))
g = m2 - l2
k.append(g)
if [item for item in k if k.count(item) <= 1]:
count += 1
else:
return k

Your list k has just one element being appended prior to starting the loop. Therefore it is list of length of one, therefore it runs just once.
Rethink your algorythm.

Related

How do I find the index of variable b from list a?

How do I find the index of variable b from list a?
I suspect that the problem is in the data types.
a=[-202516736, '-202516736', '13886', '678280946', '14514', '330251838', '14511', '639566631', '14510', '542472303', '14506']
b=['678280946']
a_INT = [int(item) for item in a]
b_INT = [int(item) for item in b]
j = 0
while True:
try:
i = a_INT.index(b_INT, j)
print(i)
j = i + 1
except:
break
Let's take this a step further and add another value to the b list and also add a duplicate in the a list. Then:
a=[-202516736, '-202516736', '13886', '678280946', '14514', '678280946', '330251838', '14511', '639566631', '14510', '542472303', '14506']
b=['678280946', 13886]
ai = list(map(int, a))
for n in map(int, b):
offset = 0
r = []
while True:
try:
i = ai[offset:].index(n)
r.append(offset+i)
offset += i + 1
except ValueError:
break
print(f'{n} occurs at {r}')
Output:
678280946 occurs at [3, 5]
13886 occurs at [2]
Version 2:
The first piece of code is functionally correct. However, it could be very inefficient if the list being searched is very large.
Python's built-in sort function is very fast. So, let's build a list of 2-tuples each made up of a value from the list and its original index. Then sort the new list. Now that it's sorted we can perform a binary search and move on from there.
Added some more values to the OP's original list for demonstration purposes:
a = [-202516736, '-202516736', '13886', '678280946', '14514', '678280946',
'330251838', '14511', '639566631', '14510', '542472303', '14506', '678280946']
b = ['678280946', 13886, 14514, '-202516736', 99]
def bsearch(lst, x):
L = 0
R = len(lst) - 1
while L <= R:
m = (L + R) // 2
if (v := lst[m][0]) == x:
return m
if v < x:
L = m + 1
else:
R = m - 1
return -1
def findall(list_, n):
templist = sorted((v, i) for i, v in enumerate(list_))
result = None
if (i := bsearch(templist, n)) >= 0:
result = [templist[i][1]]
for j in range(i-1, -1, -1):
if templist[j][0] != n:
break
result.append(templist[j][1])
for j in range(i+1, len(templist)):
if templist[j][0] != n:
break
result.append(templist[j][1])
return result
ai = list(map(int, a))
for n in map(int, b):
print(f'{n} -> {findall(ai, n)}')
Output:
678280946 -> [5, 3, 12]
13886 -> [2]
14514 -> [4]
-202516736 -> [0, 1]
99 -> None
a=[-202516736, '-202516736', '13886', '678280946', '14514', '330251838', '14511', '639566631', '14510', '542472303', '14506']
b=['678280946']
for item in b:
print(a.index(item))
Since b has only one element the output is 3.

Printing all subsets with only a given length in python

I have the task to print all subsets of given length, I have created the functions to print out the all the subsets. Everything works fine the subsets are generated, but the output is wrong for each call. For example if I call print(get_subsets([1,2,3],2)) the output is [1,2] [1,3] [2,3] and [3]. Of course 3 is not supposed to be there and I can't figure out why. Any help will be appreciated and feedback of course.
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
for curr_subset in all_subsets:
if len(curr_subset) > k or len(curr_subset) < k:
all_subsets.remove(curr_subset)
return all_subsets
def _gen_subsets(nums,curr_idx, curr_subset, all_subsets):
if curr_idx >= len(nums):
all_subsets.append(curr_subset)
else:
itr_subset = curr_subset.copy()
itr_subset.append(nums[curr_idx])
_gen_subsets(nums=nums,
curr_idx=curr_idx+1,
curr_subset=itr_subset,
all_subsets=all_subsets)
_gen_subsets(nums=nums,
curr_idx=curr_idx+1,
curr_subset=curr_subset,
all_subsets=all_subsets)
You are trying to iterate through a list from which you are also removing elements. This messed up the position and index of the list of subsets and gave you the wrong output.
Change the function get_subsets to this:
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
final_subset = all_subsets.copy()
for n in all_subsets:
if len(n) != k:
final_subset.remove(n)
return final_subset
Or this:
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
all_subsets = [n for n in all_subsets if len(n) == k]
return all_subsets
Your problem is caused by this:
for curr_subset in all_subsets:
if len(curr_subset) > k or len(curr_subset) < k:
all_subsets.remove(curr_subset)
You are removing array elements while iterating. That leads to the following scenario: Initially you have array [X1, X2, X3].
In the first iteration, you remove the first element X1. Then the second element X2 becomes the first element and therefore, on the second iteration, the third element X3 (which has become the second element) is traversed and X2 is skipped. That is why [3] is not removed from your array.
To solve this, you can change get_subsets function as below:
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
all_subsets = [subset for subset in all_subsets if len(subset) == k]
return all_subsets
maybe thes two will help you?
def Combinations(l, d):
if (d <= 1) or (len(l) <= 1):
return [[i] for i in l]
else:
result = []
for i in range(len(l)):
c = l[i]
lx = l[:i]+l[i+1:]
for cmb in Combinations(lx, d-1):
result.append([c]+cmb)
return result
print(*Combinations([1, 2, 3, 4, 5, 6], 2), sep='\n')
def Allocations(l, d):
if (d <= 1) or (len(l) <= 1):
return [[i] for i in l]
else:
result = []
for i in range(len(l)+1-d):
c = l[i]
lx = l[i+1:]
for cmb in Allocations(lx, d-1):
result.append([c]+cmb)
return result
print(*Allocations([1, 2, 3, 4, 5, 6], 3), sep='\n')

Finding first pair of numbers in array that sum to value

Im trying to solve the following Codewars problem: https://www.codewars.com/kata/sum-of-pairs/train/python
Here is my current implementation in Python:
def sum_pairs(ints, s):
right = float("inf")
n = len(ints)
m = {}
dup = {}
for i, x in enumerate(ints):
if x not in m.keys():
m[x] = i # Track first index of x using hash map.
elif x in m.keys() and x not in dup.keys():
dup[x] = i
for x in m.keys():
if s - x in m.keys():
if x == s-x and x in dup.keys():
j = m[x]
k = dup[x]
else:
j = m[x]
k = m[s-x]
comp = max(j,k)
if comp < right and j!= k:
right = comp
if right > n:
return None
return [s - ints[right],ints[right]]
The code seems to produce correct results, however the input can consist of array with up to 10 000 000 elements, so the execution times out for large inputs. I need help with optimizing/modifying the code so that it can handle sufficiently large arrays.
Your code inefficient for large list test cases so it gives timeout error. Instead you can do:
def sum_pairs(lst, s):
seen = set()
for item in lst:
if s - item in seen:
return [s - item, item]
seen.add(item)
We put the values in seen until we find a value that produces the specified sum with one of the seen values.
For more information go: Referance link
Maybe this code:
def sum_pairs(lst, s):
c = 0
while c<len(lst)-1:
if c != len(lst)-1:
x= lst[c]
spam = c+1
while spam < len(lst):
nxt= lst[spam]
if nxt + x== s:
return [x, nxt]
spam += 1
else:
return None
c +=1
lst = [5, 6, 5, 8]
s = 14
print(sum_pairs(lst, s))
Output:
[6, 8]
This answer unfortunately still times out, even though it's supposed to run in O(n^3) (since it is dominated by the sort, the rest of the algorithm running in O(n)). I'm not sure how you can obtain better than this complexity, but I thought I might put this idea out there.
def sum_pairs(ints, s):
ints_with_idx = enumerate(ints)
# Sort the array of ints
ints_with_idx = sorted(ints_with_idx, key = lambda (idx, num) : num)
diff = 1000000
l = 0
r = len(ints) - 1
# Indexes of the sum operands in sorted array
lSum = 0
rSum = 0
while l < r:
# Compute the absolute difference between the current sum and the desired sum
sum = ints_with_idx[l][1] + ints_with_idx[r][1]
absDiff = abs(sum - s)
if absDiff < diff:
# Update the best difference
lSum = l
rSum = r
diff = absDiff
elif sum > s:
# Decrease the large value
r -= 1
else:
# Test to see if the indexes are better (more to the left) for the same difference
if absDiff == diff:
rightmostIdx = max(ints_with_idx[l][0], ints_with_idx[r][0])
if rightmostIdx < max(ints_with_idx[lSum][0], ints_with_idx[rSum][0]):
lSum = l
rSum = r
# Increase the small value
l += 1
# Retrieve indexes of sum operands
aSumIdx = ints_with_idx[lSum][0]
bSumIdx = ints_with_idx[rSum][0]
# Retrieve values of operands for sum in correct order
aSum = ints[min(aSumIdx, bSumIdx)]
bSum = ints[max(aSumIdx, bSumIdx)]
if aSum + bSum == s:
return [aSum, bSum]
else:
return None

Find/extract a sequence of integers within a list in python

I want to find a sequence of n consecutive integers within a sorted list and return that sequence. This is the best I can figure out (for n = 4), and it doesn't allow the user to specify an n.
my_list = [2,3,4,5,7,9]
for i in range(len(my_list)):
if my_list[i+1] == my_list[i]+1 and my_list[i+2] == my_list[i]+2 and my_list[i+3] == my_list[i]+3:
my_sequence = list(range(my_list[i],my_list[i]+4))
my_sequence = [2,3,4,5]
I just realized this code doesn't work and returns an "index out of range" error, so I'll have to mess with the range of the for loop.
Here's a straight-forward solution. It's not as efficient as it might be, but it will be fine unless you have very long lists:
myarray = [2,5,1,7,3,8,1,2,3,4,5,7,4,9,1,2,3,5]
for idx, a in enumerate(myarray):
if myarray[idx:idx+4] == [a,a+1,a+2,a+3]:
print([a, a+1,a+2,a+3])
break
Create a nested master result list, then go through my_sorted_list and add each item to either the last list in the master (if discontinuous) or to a new list in the master (if continuous):
>>> my_sorted_list = [0,2,5,7,8,9]
>>> my_sequences = []
>>> for idx,item in enumerate(my_sorted_list):
... if not idx or item-1 != my_sequences[-1][-1]:
... my_sequences.append([item])
... else:
... my_sequences[-1].append(item)
...
>>> max(my_sequences, key=len)
[7, 8, 9]
A short and concise way is to fill an array with numbers every time you find the next integer is the current integer plus 1 (until you already have N consecutive numbers in array), and for anything else, we can empty the array:
arr = [4,3,1,2,3,4,5,7,5,3,2,4]
N = 4
newarr = []
for i in range(len(arr)-1):
if(arr[i]+1 == arr[i+1]):
newarr += [arr[i]]
if(len(newarr) == N):
break
else:
newarr = []
When the code is run, newarr will be:
[1, 2, 3, 4]
#size = length of sequence
#span = the span of neighbour integers
#the time complexity is O(n)
def extractSeq(lst,size,span=1):
lst_size = len(lst)
if lst_size < size:
return []
for i in range(lst_size - size + 1):
for j in range(size - 1):
if lst[i + j] + span == lst[i + j + 1]:
continue
else:
i += j
break
else:
return lst[i:i+size]
return []
mylist = [2,3,4,5,7,9]
for j in range(len(mylist)):
m=mylist[j]
idx=j
c=j
for i in range(j,len(mylist)):
if mylist[i]<m:
m=mylist[i]
idx=c
c+=1
tmp=mylist[j]
mylist[j]=m
mylist[idx]=tmp
print(mylist)

While loop code keeps running

For some reason this code doesn't print anything and doesn't stop running, can anybody tell me what is going wrong here?
l = [1,2]
i = 0
k = l[i]+l[i+1]
while k <= 10:
l.append(k)
i += 1
print l
The value of k (and therefore the loop condition) is set before the loop using the current value of i (0), and never changes during the loop execution. You would have to reassign k based on the new value for i inside the loop for it to change.
Python evaluates the value of k so that k isn't the expression, but the result of that expression:
k = l[i]+l[i+1] # In your case it's l[0] + l[1] = 3
You probably want to evaluate k every loop:
l = [1,2]
i = 0
for i in range(0, 10 + 1):
l.append(l[i] + l[i + 1])
print l
And just for fun, a more Pythonic Fibonacci sequence generator (literally):
def Fibonacci():
a, b = 0, 1
while True:
yield a
a += b
a, b = b, a
for n in Fibonacci():
raw_input(n)
Just move the line with k in it:
l = [1,2]
i = 0
k = l[i]+l[i+1]
while k <= 10:
l.append(k)
i += 1
k = l[i]+l[i+1]
print l
You're not doing any changes to the k variable. Once you calculate the value of K, the code gets stock in the while loop because the value of k never changes, you simply keep appending the value of k to the list.
not sure about python,
but looks like you update the value of K ever also, not sure what is the scope of the while loop in python syntax.

Categories