How to increment the outer iterator from the inner loop?
To be more precise:
for i in range(0,6):
print i
for j in range(0,5):
i = i+2
I am getting
0
1
2
3
4
5
, but I want 0,2,4
Above is the simpilfied idea what I want to acheive.
Here is my Java code:
str1="ababa"
str2="aba"
for(int i =0; i < str1.length; i++)
for(int j =0; j < str2.length; j++)
if str1[i+j]!=str[j]
break;
if( j ==str2.length -1)
i=i+str2.length;
It seems that you want to use step parameter of range function. From documentation:
range(start, stop[, step]) This is a versatile function to create
lists containing arithmetic progressions. It is most often used in for
loops. The arguments must be plain integers. If the step argument is
omitted, it defaults to 1. If the start argument is omitted, it
defaults to 0. The full form returns a list of plain integers [start,
start + step, start + 2 * step, ...]. If step is positive, the last
element is the largest start + i * step less than stop; if step is
negative, the last element is the smallest start + i * step greater
than stop. step must not be zero (or else ValueError is raised).
Example:
>>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(1, 11) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> range(0, 30, 5) [0, 5, 10, 15, 20, 25]
>>> range(0, 10, 3) [0, 3, 6, 9]
>>> range(0, -10, -1) [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
>>> range(0) []
>>> range(1, 0) []
In your case to get [0,2,4] you can use:
range(0,6,2)
OR in your case when is a var:
idx = None
for i in range(len(str1)):
if idx and i < idx:
continue
for j in range(len(str2)):
if str1[i+j] != str2[j]:
break
else:
idx = i+j
You might just be better of using while loops rather than for loops for this. I translated your code directly from the java code.
str1 = "ababa"
str2 = "aba"
i = 0
while i < len(str1):
j = 0
while j < len(str2):
if not str1[i+j] == str1[j]:
break
if j == (len(str2) -1):
i += len(str2)
j+=1
i+=1
In python, for loops iterate over iterables, instead of incrementing a counter, so you have a couple choices. Using a skip flag like Artsiom recommended is one way to do it. Another option is to make a generator from your range and manually advance it by discarding an element using next().
iGen = (i for i in range(0, 6))
for i in iGen:
print i
if not i % 2:
iGen.next()
But this isn't quite complete because next() might throw a StopIteration if it reaches the end of the range, so you have to add some logic to detect that and break out of the outer loop if that happens.
In the end, I'd probably go with aw4ully's solution with the while loops.
I read all the above answers and those are actually good.
look at this code:
for i in range(1, 4):
print("Before change:", i)
i = 20 # changing i variable
print("After change:", i) # this line will always print 20
When we execute above code the output is like below,
Before Change: 1
After change: 20
Before Change: 2
After change: 20
Before Change: 3
After change: 20
in python for loop is not trying to increase i value. for loop is just assign values to i which we gave. Using range(4) what we are doing is we give the values to for loop which need assign to the i.
You can use while loop instead of for loop to do same thing what you want,
i = 0
while i < 6:
print(i)
j = 0
while j < 5:
i += 2 # to increase `i` by 2
This will give,
0
2
4
Thank you !
for a in range(1):
for b in range(3):
a = b*2
print(a)
As per your question, you want to iterate the outer loop with help of the inner loop.
In outer loop, we are iterating the inner loop 1 time.
In the inner loop, we are iterating the 3 digits which are in the multiple of 2, starting from 0.
Output:
0
2
4
Related
I need to change the condition so that the loop is finite and list_ contains following values:
1 2 4 8 16 32 64
This is what I have in python, and I am struggling to understand what exactly needs to be changed and why.
list_ = []
i = 0
while i >= 0: # change the condition
list_.append(2 ** i)
i += 1
print(list_)
I suggest to use a for-loop instead of a while loop.
list_ = []
for i in range(7):
list_.append(2 ** i)
print(list_)
If you want to be very pythonic, then you can use a list comprehension:
list_ = [2 ** i for i in range(7)]
With a while a breaking condition is required (this implementation is to highlight the break)
out = []
i = 0
while True:
if i > 6:
break
out.append(2**i)
i += 1
print(out)
or with a list comprehension
print([2**i for i in range(6+1)])
Looks like you'll only need to switch the while condition in the loop. Rather than have a lower bound, you'll need to update with an upper bound - basically a "loop until" condition.
list_ = []
i = 0
while i <= 6: # change the condition
list_.append(2 ** i)
i += 1
print(list_). # [1, 2, 4, 8, 16, 32, 64]
But you can simplify this even further, with the help of a list comprehension. This is just a fancy (and bit more efficient) way of writing a for loop in python. Its more efficient because it doesn't need to call list.append within each loop iteration.
>>> [2 ** i for i in range(7)]
[1, 2, 4, 8, 16, 32, 64]
You could use while i <= 6: so that you while loop counts up to i=6.
However, I would recommend to use a for-loop with range(6) as a condition. So that your loop looks like the following:
for i in range(7):
…
This is just an alternative way, where i also counts up to the value of 6. using a for-loop would be good practice, as it saves you to declare i previously.
I tried to solve the problem below using dynamic programming, but there is something wrong with my code and I could not figure it out. Could you help me with it? Thank you!
Problem:
Given two arrays of length m and n with digits 0-9 representing two numbers. Create the maximum number of length k <= m + n from digits of the two. The relative order of the digits from the same array must be preserved. Return an array of the k digits.
Note: You should try to optimize your time and space complexity.
Example 1:
Input:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
Output:
[9, 8, 6, 5, 3]
Example 2:
Input:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
Output:
[6, 7, 6, 0, 4]
Example 3:
Input:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
Output:
[9, 8, 9]
My idea is as following:
dp[i][j][t] is the the maximum number of length i which is picked out of first j digits of array 1 and first t digits of array 2, where i goes from 0 to k, j goes from 0 to len(nums1), t goes from 0 to len(nums2). the state transition equation goes like this:
when nums1[j-1] > nums2[t-1]:
if we already have k-2 digits, then we have to take both nums1[j-1] and nums2[t-1], and we must take nums1[j-1] first in order to maximize the result
if we already have k-1 digits, then we only have to take one more digit, and it must be nums1[j-1], because it is bigger
if we already have k digits, then we do not need to take more digits, so we keep the last result dp[i][j-1][t-1]
Given that we are looking for maximum, our current result should be the biggest among these 3 situations, so we have:
dp[i][j][t] = max(
(dp[i-2][j-1][t-1]*10+nums1[j-1])*10+nums2[t-1],
dp[i-1][j-1][t-1]*10+nums1[j-1],
dp[i][j-1][t-1]
)
when nums1[j-1] < nums2[t-1]:
if we already have k-2 digits, then we have to take both nums1[j-1] and nums2[t-1], and this time we must take nums2[t-1] first because it is bigger
if we already have k-1 digits, then we only have to take one more digit, and it must be nums2[t-1], because it is bigger
if we already have k digits, then we do not need to take more digits, so we keep the last result dp[i][j-1][t-1]
Likewise, we take the biggest result from these possible ones:
dp[i][j][t] = max(
(dp[i-2][j-1][t-1]*10+nums2[t-1])*10+nums1[j-1],
dp[i-1][j-1][t-1]*10+nums2[t-1],
dp[i][j-1][t-1]
)
Here is my code:
import numpy as np
def maxNumber(nums1, nums2, k):
m = len(nums1)
n = len(nums2)
dp = [[[0 for _ in range(n + 1)] for _ in range(m + 1)] for _ in range(k + 1)]
for i in range(2, k + 1):
for j in range(i + 1):
if j > m or (i - j) > n:
continue
tmp = 0
tmp_nums1 = nums1[:j]
tmp_nums2 = nums2[:(i-j)]
while tmp_nums1 or tmp_nums2:
if tmp_nums1 > tmp_nums2:
tmp = tmp * 10 + tmp_nums1.pop(0)
else:
tmp = tmp * 10 + tmp_nums2.pop(0)
dp[i][j][i - j] = tmp
for i in range(m + 1):
for j in range(n + 1):
if not i and not j:
continue
dp[1][i][j] = max(nums1[:i] + nums2[:j])
for i in range(2, k+1):
for j in range(m+1):
for t in range(i+1-j, n + 1):
if nums1[j - 1] > nums2[t - 1]:
dp[i][j][t] = max((dp[i-2][j-1][t-1]*10+nums1[j-1])*10+nums2[t-1], dp[i][j-1][t-1], dp[i-1][j-1][t-1]*10+nums1[j-1])
else:
dp[i][j][t] = max((dp[i-2][j-1][t-1]*10+nums2[t-1])*10+nums1[j-1], dp[i][j-1][t-1], dp[i-1][j-1][t-1]*10+nums2[t-1])
# print(np.array(dp))
res = []
tmp_res = dp[-1][-1][-1]
while tmp_res:
res.append(tmp_res % 10)
tmp_res //= 10
return res[::-1]
But it outputs [8, 9, 9] on Example 3, and I cannot figure out the reason. Could you help me with it?
Thank you in advance!
Dynamic programming usually implies short-circuiting some of the computation based on results from computations made to date. Often this takes the form of a recursive function. You seem to be taking more of a brute force approach (which usually corresponds to the worse case scenario for dp)
Here is an example of a recursive approach that will lend itself better to optimization:
def largestFrom(M,N,K):
if K == 1: return [max(M+N)] # simple case
if not M and len(N)==K : return N # simple case
if not N and len(M)==K : return M # simple case
result = []
for A,B in [(N,M),(M,N)]:
for i,a in enumerate(A): # trial on numbers from A
if len(A)-i+len(B)<K: break # can't take more from A
if result and a < result[0]: continue # short-circuit
R = [a] + largestFrom(A[i+1:],B,K-1) # recurse with remaining numbers
if R > result: result = R # track best so far
return result
After eliminating the obvious solutions that require no special processing, it goes into a recursive trial/error process that short-circuits the traversal for candidate numbers that won't improve the best result found so far.
The traversal goes through the two lists and attempts to use the number at each position as the first one in the result. It then recurses with the remaining numbers and a size of K-1. So, upon returning from the recursion, a list R is formed of the selected number followed by the largest K-1 sized suffix that can be made with the remaining numbers.
One part of the short circuiting is stopping the loop when the index of the selected number would not leave enough remaining numbers to reach a size of K-1 (i.e. combining the remainder of the current list plus all numbers of the other one).
Another part of short circuiting is comparing the number we are about to try with the first one in the best result. If the candidate number is smaller than the first one in the result, then it would be pointless to go deeper as there is no possibility to form an R list greater than the result we already have.
For example:
combining [3,9] [8,9] with K=3
result starts empty
Going through first list [3,9]
select 3 at position 0
recurse with M=[9] N=[8,9] K=2
will produce R = [3] + [9,8]
R > result, result is now [3,9,8]
select 9 at position 1
recurse with M=[] N=[8,9] K=2
will produce R = [9] + [8,9]
R > result, result is now [9,8,9]
Going through second list [8,9]
select 8 at position 0
8 is smaller than R[0] (9)
short-circuit
select 9 at position 1
recurse with M=[3,9] N=[] K=2
will produce R = [9] + [3,9]
result unchanged (R is < result)
return result [9,8,9]
The for A,B in [(N,M),(M,N)]: loop is merely a shorthand way to avoid duplicating the code for the trial loops on numbers in M and numbers N.
testSet = [ ([3,4,6,5],[9,1,2,5,8,3],5),
([6, 7], [6, 0, 4],5),
([3, 9], [8, 9],3)
]
for M,N,K in testSet:
print(M,N,K,":",largestFrom(M,N,K))
[3, 4, 6, 5] [9, 1, 2, 5, 8, 3] 5 : [9, 8, 6, 5, 3]
[6, 7] [6, 0, 4] 5 : [6, 7, 6, 0, 4]
[3, 9] [8, 9] 3 : [9, 8, 9]
There is alternative way than DP to solve it. Here I've just crafted another solution:
def maxNumber(nums1, nums2, k):
def pick(nums, k):
stack = []
drop = len(nums) - k
for num in nums:
while drop and stack and stack[-1] < num:
stack.pop()
drop -= 1
stack.append(num)
return stack[:k]
def merge(A, B):
ans = []
while A or B:
bigger = A if A > B else B
ans.append(bigger.pop(0))
return ans
return max(merge(pick(nums1, i), pick(nums2, k-i))
for i in range(k+1) if i <= len(nums1) and k-i <= len(nums2))
if __name__ == '__main__':
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
print(maxNumber(nums1, nums2, 5))
print(maxNumber([3,9],[8,9], 3))
Are those answers to your examples provided by the professor? Because they don't make sense to me. Surely the largest number is one that uses all of the digits available? i.e. the largest value will always mean k=m+n. You can't possibly have a larger answer with k=m+(n-1) for instance. What am I missing?
Example 3:
Input: nums1 = [3, 9]
nums2 = [8, 9]
k = 3
Output: [9, 8, 9]
or - in my world k = 4 / Output: [8, 9, 3, 9]
(Hmm... I guess they were provided. Seems a weird question to me. Sorry - I'm unable to help, but I'll post this anyway in case someone else wonders the same thing I did. To me the hard part would be to actually work out what the largest number would be, using all digits. But even then that's not that hard: Compare positions 1 - use the value from the larger array. Compare position 1 of the non-chosen array with position 2... and so on.)
I followed an algorithm with a while loop, but one of the parameters of the question was that I use nested for loops, and I'm not sure how to do that.
This is the while loop:
i = len(lst)
while i > 0:
big = lst.index(max(lst[0:i]))
lst[big], lst[i-1] = lst[i-1], lst[big]
i = i - 1
return lst
This is the question it's answering:
Input: [5,1,7,3]
First, find the largest number, which is 7.
Swap it and the number currently at the end of the list, which is 3. Now we have: [5,1,3,7]
Now, find the largest number, not including the 7, which is 5.
Swap it and the second to last number, which is 3. Now we have: [3,1,5,7].
Now, find the third largest number (excluding the first two), which is 3.
Swap it and the third to last number, which is 1.
Output: [1, 3, 5, 7]
What you're seeing in the algorithm is a selection sort. And here's your second solution which you asked (nested for loops):
def insertion_sort(arr):
l = len(arr)
for i in range(l-1, -1, -1):
m = -10000 # it should be lower than min(arr)
idx = -1
for key, val in enumerate(arr[:i+1]):
if m < val:
m = val
idx = key
if idx != -1:
arr[i], arr[idx] = arr[idx], arr[i]
return arr
And a quick test:
arr = list(range(10))[::-1]
print(arr)
# prints [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
result = insertion_sort(arr)
print(result)
# prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
This looks like a (rather slow) sorting algorithm - namely bubble sort. It's iterating from the end of the list lst. Then it's searching for the maximum value in the first n-1 elements, and swapping them with the end. It will, however, fail, if the maximum value is already at the end, because then it will automatically swap the max(n-1) with the n value. You'll need to add a check for this.
So from a first look, I'm not sure if i is defined before, but let's assume it's defined at the length of the list lst, as it seems to be. So let's start with the outer loop - as have a while loop that looks like it's counting down from i to 0. This is the opposite of an increasing for-loop, so we can create a reserved range:
rev_range = range(0,len(lst))
rev_range.reverse()
for j in rev_range:
# perform the sort
We now have the outer loop for the counting-down while loop. The sort itself iterates forward until it finds the maximum. This is a forward for loop.
# sorting
max_val_so_far_index=lst[j]
# lst[:j-1] gets the first j-1 elements of the list
for k in lst[:j-1]:
if lst[k] > lst[max_val_so_far_index]:
max_val_so_far_index = k
# now we have the index of the maximum value
# swap
temp = lst[j]
lst[j] = lst[max_val_so_far_index]
lst[max_val_so_far_index]=temp
Let's put the two components together to get:
rev_range = range(0,len(lst))
rev_range.reverse()
for j in rev_range:
# perform the sort
# sorting
#print j
max_val_so_far_index=j
# get the first j items
for k in range(j):
if lst[k] > lst[max_val_so_far_index]:
max_val_so_far_index = k
# now we have the index of the maximum value
# swap
temp = lst[j]
lst[j] = lst[max_val_so_far_index]
lst[max_val_so_far_index]=temp
At the end lst is sorted.
The algorithm in the question is just another form of a bubble sort. The original algorithm uses two nested for loops. You can find a good explaination here.
I'm trying to create an array of positive and negative integers, representing distances north and south of a location - I need to see the elements of the array in zigzag order.
This means that the largest member appears first, the smallest member appears second, and the remaining elements alternate between the larger members decreasing from the largest and the smaller members increasing from the smallest.
I.e. the array [1, 3, 6, 9, -3] becomes [9, -3, 6, 1, 3].
I'm trying to complete the function wiggleArrangeArray, which takes one argument, an integer array of n integers.
Required Input Format, Constraints, and Output Format
I'm not sure how to say
"if the item in the array is larger than the other items in the array, display it first."
"if the item is smaller than the other items in the array, display it second."
"then alternate between the next largest numbers, and the next smallest numbers"
def wiggleArrangeArray(intArr):
for i in intArr
#if i > other items in intArr
#display that i at index value 0
#if i < other items in intArr
#display that i at index value 1
#if i < i at index value 0 and > other items in intArr, display it next
#if i > i at index value 1 and < other items in intArr, display it next
#repeat last two lines for continuing values
Please help if possible. Here's a link to the solution in C++ but I need it in Python. Thanks.
Edit: The function needs to work with the following tests:
f = open(os.environ["OUTPUT_PATH"], "w")
_intArr_cnt = int(raw_input())
_intArr_i=0
_intARR = []
while _intArr_i < _intArr_cnt:
_intArr_item = int(raw_input());
_intArr.append(_intArr_item)
_intArr_i+=1
res = wiggleArrangeArray(_intArr);
for res_cur in res:
f.write( str(res_cur) + "\n" )
f.close()
The altered C++ code
Note the algorithm you provided does calculate some sort of zigzag, but it is not the zigzag you are looking for. For future reference I will leave it here.
In the C++ code you provided, they only look for a sequences that satisfies a < b > c < d > e < f, you are looking however for a sequence with the 1-max, 1-min, 2-max, 2-min,...
Your link provides you a solution which you can copy nearly verbatim in Python. You only define a swap function:
def swap(arr,i,j):
t = arr[i]
arr[i] = arr[j]
arr[j] = t
Next you can simply modify the code:
def zigZag(arr):
n = len(arr)
# Flag true indicates relation "<" is expected,
# else ">" is expected. The first expected relation
# is "<"
flag = True
i = 0
while i<= n-2:
if (flag): # "<" relation expected
# If we have a situation like A > B > C,
# we get A > B < C by swapping B and C
if arr[i] > arr[i+1]:
swap(arr,i,i+1)
else: # ">" relation expected
# If we have a situation like A < B < C,
# we get A < C > B by swapping B and C
if arr[i] < arr[i+1]:
swap(arr,i,i+1)
flag = not flag # flip flag
i += 1
Mind that this is rather un-Pythonic, so you can simply improve it like:
def swap(arr,i,j):
arr[i],arr[j] = arr[j],arr[i]
def zigZag(arr):
n = len(arr)
for i in range(len(arr)-1):
if not i&1:
if arr[i] > arr[i+1]:
swap(arr,i,i+1)
elif arr[i] < arr[i+1]:
swap(arr,i,i+1)
return arr
Here tuple assignment is used to swap elements in the list, a range is used to iterate over the indices, we can furthermore use an elif instead of an if in an else, and for I've abandoned the flag by using a modulo check.
Your zigzag function
You can simply solve the problem by sorting the list, and using two pointers that each time emit the most left, the most right and walk towards each other. In other words something like:
def zigZag(arr):
srt = sorted(arr)
left = 0
right = len(srt)-1
result = []
while left < right:
result.append(srt[right])
right -= 1
if left < right:
result.append(srt[left])
left += 1
return result
Here Python implementation example.
Sort your data in reversed order (9, 6, 3, 1, -3)
Split by two lists (9, 6) (3, 1, -3)
Iterate over both (using zip_longest) first one from start, second in reverse order (9, -3), (6, 1) (None, 3)
Unpack tuples created by zip_longest (chain(*zip...)) so you get iterable data (9, -3, 6, 1, None, 3)
Remove None value in case if the list has an odd number of elements (if x is not None)
Example:
from itertools import zip_longest, chain
def zig_zag_array(data):
data = sorted(data)
mid = len(data) // 2
return [
x for x in chain(*zip_longest(data[mid:][::-1], data[:mid])) if x is not None
]
Test:
if __name__ == "__main__":
data = [1, 3, 6, 9, -3]
expected = [9, -3, 6, 1, 3]
output = zig_zag_array(data)
assert output == expected, f"Odd length: {output=}"
data = [1, 3, 6, 9, -3, 0]
expected = [9, -3, 6, 0, 3, 1]
output = zig_zag_array(data)
assert output == expected, f"Even length: {output=}"
print("PASSED")
>>> k = 8
>>> for i in range(k):
print i
k -= 3
print k
Above the is the code which prints numbers from 0-7 if I use just print i in the for loop.
I want to understand the above code how it is working, and is there any way we can update the value of variable used in range(variable) so it iterates differently.
Also why it always iterates up to the initial k value, why the value doesn't updated.
I know it's a silly question, but all ideas and comments are welcome.
You can't change the range after it's been generated. In Python 2, range(k) will make a list of integers from 0 to k, like this: [0, 1, 2, 3, 4, 5, 6, 7]. Changing k after the list has been made will do nothing.
If you want to change the number to iterate to, you could use a while loop, like this:
k = 8
i = 0
while i < k:
print i
k -= 3
i += 1
The expression range(k) is evaluated just once, not on every iteration. You can't set k and expect the range(k) result to change, no. From the for statement documentation:
The expression list is evaluated once; it should yield an iterable object.
You can use a while loop instead:
i = 0
k = 8
while i < k:
print i
i += 1
k -= 3
A while loop does re-evaluate the test each iteration. Referencing the while statement documentation:
This repeatedly tests the expression and, if it is true, executes the first suite
If you do want to change k and affect the loop you need to make sure you are iterating over mutable object. For example:
k = list(range(8))
for i in k:
print(i)
k.pop()
k.pop()
k.pop()
print(k)
Or alternatively:
k = list(range(8))
for i in k:
print(i)
k[:] = k[:-3]
print(k)
Both will result with
0
[0, 1, 2, 3, 4]
1
[0, 1]
you could do it like this ,I think, but I dont know if this is what you want.
def to_infinity():
index = 0
while True:
yield index
index += 1
for i in to_infinity():
print(i)