I have been asked an interview question to reverse an array. I used the following method and it worked as expected:
def reverse(array, i, j):
if i > j: # ensure i <= j
i, j = j, i
while i < j:
array[i], array[j] = array[j], array[i]
i += 1
j -= 1
Now, the interviewer asked me to replace the above while loop by for and I was really confused. Please can someone help me here. Thanks in advance.
This is not a for, but you can also do this:
If you follow the python logic where [i:j] means i <= x < j then you can do this:
array[i:j] = array[j-1:i-1:-1]
Other way, if you want to get the elements where i <= x <= j then you can do as #darksky suggested:
array[i:j+1] = array[j: i - 1: -1]
You could forget the for loop entirely and do something like this:
def reverse(array, i, j):
# Make sure i is less than j
if i > j:
i, j = j, i
# Reverse array[i:j+1]
section = array[i:j+1]
section.reverse()
array[i:j+1] = section
(The j+1 is to keep consistent with your function's behaviour; both i and j are treated as inclusive, but Python wants [inclusive, exclusive).)
Or if you want to keep the for loop in and avoid standard functions, then you could do something like this:
def reverse(array, i, j):
# Make sure i is less than j
if i > j:
i, j = j, i
# Reverse array[i:j]
count = j - i + 1
for offset in range(0, count // 2):
first = i + offset
second = j - offset
array[first], array[second] = array[second], array[first]
Other answers here perform this in a really smart way, but a for loop should look something like:
for x in range(j - i):
array[i+x], array[j-x] = array[j-x], array[i+x]
I think more readable example would be:
arr[i,j] = reversed(arr[i, j])
Related
I have the following code (in Python):
while i != 0 and j != 0:
possibAct, posX, posY = possibleActions(i, j)
i, j = constructValueFunction_GetOptimalAction(possibAct, posX, posY)
possibAct, i, j = possibleActions(i, j)
Seems like it stops when only one (i or j) gets to 0, but what I want is to make it stop only when both are 0. What am I missing?
You can give or like this:
while i!=0 or j!=0:
(some code)
when i is 0 ,j may not be 0 so it waits for j to become 0
With your current code, loop will break when any of i,j gets 0 as i!=0 and j!=0 becomes False. You need something like the following, in order to stop the loop only if both i and j become 0:
while not (i == 0 and j == 0):
possibAct, posX, posY = possibleActions(i, j)
i, j = constructValueFunction_GetOptimalAction(possibAct, posX, posY)
possibAct, i, j = possibleActions(i, j)
You can just replace and with or
I have an implementation of the Insertionsort algorithm where in the lecture there is a new instance variable before the while loop.
def swap(l, i, j):
temp = l[i]
l[i] = l[j]
l[j] = temp
def ins_sort(l):
for i in range(len(l)):
j = i
while j > 0 and l[j - 1] > l[j]:
swap(l, j - 1, j)
j = j - 1
return l
In my testing and playing around the algorithm worked without it as well though and I do not understand why I would need to write an extra line of code if it is not necessary.
def swap(l, i, j):
temp = l[i]
l[i] = l[j]
l[j] = temp
def ins_sort(l):
for i in range(len(l)):
while i > 0 and l[i - 1] > l[i]:
swap(l, i - 1, i)
i = i - 1
return l
It looks like the original code is a translation from the c/c++ implementation where modifying i inside the loop would be persistent and affect the loop itself. However since in python, i will be reset each iteration, the second code will also work.
In short I don't think that line is necessary for a python implementation.
ref:Scope of python variable in for loop
You could also try the following program for Insertion sort where the use of the extra variable is not necessary:
l=[4,3,1,2]
for i in range(1,len(l)):
key=l[i]
for j in range(i-1,-1,-1):
if l[j]>key:
l[j+1]=l[j]
else:
j=j+1
break
l[j]=key
print(l)
I'm working on a code challenge in which I have to reduce the execution time as much as possible, the only thing I able to find where I can make an improvement is a nested if-else statement inside a nested for-loop but I'm not sure how it can be improvided.
Here's my code:
mat = [[0] * n] * n
count = 0
for i in range(n,0,-1):
count += 1
for j in range(i,n+1,1):
if i == j:
pass
else:
if getEnemyStatus(mat, i, j):
break
else:
if isEnemy(enemyDict, i, j):
setStatus(mat, i, j)
break
else:
count += 1
value of n can be from 1 to 10^5
You can skip the first if condition by starting with i+1 in range
for j in range(i+1, n+1, 1):
# code here
Second, nested if else condition should be avoided with elif for reading purpose.
Update code should be like:
mat = [[0] * n] * n
count = 0
for i in range(n,0,-1):
count += 1
for j in range(i + 1, n + 1, 1):
if getEnemyStatus(mat, i, j):
break
elif isEnemy(enemyDict, i, j):
setStatus(mat, i, j)
break
else:
count += 1
NOTE: Also if you can set the status setStatus in your isEnemy function then you can get more cleaner code:
mat = [[0] * n] * n
count = 0
for i in range(n,0,-1):
count += 1
for j in range(i + 1, n + 1, 1):
if getEnemyStatus(mat, i, j) or isEnemy(enemyDict, i, j):
break
count += 1
New to python here, so not sure if I'm posting in the right place but I was wondering why the following loop does not give an answer. I am trying to add all of the numbers previous to i, (1 + 2 + 3 + ... + i), but the loop I came up with does not complete.
j = 0
i = 17
while i > 0:
j = j + i
i - 1
print(j)
I expect j = 153, but the loop doesn't put out anything.
The issue is with i--you're not properly reducing it by 1, so this is an infinite loop. Try this:
j = 0
i = 17
while i > 0:
j = j + i
i -= 1
print(j)
Notice that your line in the while statement,
i-1, does not assign (= operator) a value to i. i stays 17 forever and ever, and so you see no output because the program gets stuck in your while loop. Try to fix your i assignment, like so:
j = 0
i = 17
while i > 0:
j = j + i
i = i - 1 # <= i = i - 1
print(j)
One way to debug your loop in the future is to put a print statement in the middle, like in the code below. The extra print statements slow your program down a bit, but you'll be able to easily see that your loop is going way more than you want!
j = 0
i = 17
while i > 0:
j = j + i
i = i - 1
print(j)
print(i) # so that we can see that i is going down :P
print(j)
Good luck :)
As noted above, you're not re-assigning to your i within the loop. But I'd also note that it's generally a bad idea to modify an iterator within the iteration loop. You can achieve the expected results in a more pythonic way using a range expression, and wrap it in a function also :)
def foo(max_num):
j = 0
for i in range(max_num+1):
j += i
return j
But even better, without the loop:
def foo(max_num):
return sum(range(max_num+1))
There are a couple of ways to do what you want to do. The way I recommend you do it is as shown below.
total = 0
i = 18
for j in range(i):
total += j
print(total)
The range(i) takes a maximum number i, and allows you to iterate through every number starting from 0 to i-1 (e.g. i = 5 will add numbers 0,1,2,3,4), therefore always make i one more than you need it to be if you want to be if you want to include the max number.
As already stated i - 1 wasn't assigned back to i
Following is a pythonic way of implementing the loop with a list comprehension
Code:
j = 0
i = 17
j = sum([j + x for x in range(i, 0, -1)])
print(j)
>>> 153
As a Function:
def sum_of_steps(start: int, stop: int, step: int) -> int:
return sum([x for x in range(start, stop, step)])
j = sum_of_steps(17, 0, -1)
print(j)
>>> 153
The function, sum_of_steps uses type hints or function annotations.
Python Basics: List Comprehensions
I'm really new at Python so I apologize in advance if this is a really dumb question. Pretty much, I'm writing a longest common subsequence algorithm with dynamic programming.
Whenever I try to run it, I get the IndexError: list index out of range, and I don't know why because the array I'm adding values to never changes in size. Code snippet for clarity:
def LCS(sequence1, sequence2):
n = len(sequence1)
m = len(sequence2)
D = [[0 for num in range(0,n)]for number in range(0, m)]
for i in range(1, n):
for j in range(1, m):
if(sequence1[i] == sequence2[j]):
D[i][j] = D[i-1][j-1] + 1
else:
D[i][j] = max(D[i-1][j], D[i][j-1])
print D[n][m]
There seem to be two problems:
In the definition of D, you should swap n and m
D = [[0 for num in range(0, m)] for number in range(0, n)]
You have to print (or better: return) the last element of the matrix
return D[n-1][m-1] # or just D[-1][-1]
The issue is with total rows and columns of the matrix(D). Size should be (m+1)*(n+1) and then loop over the matrix. Otherwise you need to return D[m-1][n-1].
def LCS(sequence1, sequence2):
n = len(sequence1)
m = len(sequence2)
D = [[0 for num in range(0,n+1)]for number in range(0, m+1)]
for i in range(1, n+1):
for j in range(1, m+1):
if(sequence1[i-1] == sequence2[j-1]):
D[i][j] = D[i-1][j-1] + 1
else:
D[i][j] = max(D[i-1][j], D[i][j-1])
print D[n][m]
LCS('abcdef' , 'defjkl')