generate a random (height x width) grid such that for every coordinate (i, j), there can be no three consecutive same colors in a row or in a column.
generate(int: width, int: height, list: colors)
Example:
getvalidMatrix(3, 3, [0, 1, 2])
output:
[
[1, 2, 1],
[1, 0, 2],
[0, 1, 2],
]
import random
def getvalidMatrix(length,width,colors):
map = dict()
for i in range(len(colors)):
map[colors[i]]=i
res = [[0] * length] * width
for i in range(length):
for j in range(width):
end = len(colors)
if i - 1 >= 0 and i - 2 >= 0 and res[i-1][j] == res[i-2][j]:
index = map[res[i-1][j]]
colors[index] = colors[end]
colors[end] = map[res[i-1]][j]
end -= 1
if j - 1 >= 0 and j - 2 >= 0 and res[i][j-1] == res[i][j-2]:
index = map[res[i][j-1]]
colors[index] = colors[end]
colors[end] = map[res[i][j-1]]
end -= 1
next=random.randint(0,end)
res[i][j] = colors[next]
return res
if __name__ == '__main__':
length = 3
width = 3
colors = [0,1,2]
print(getvalidMatrix(length, width, colors))
I got IndexError: list index out of range with the code above. Which part of the code should I fix in order to avoid the IndexError?
Although I didn't completely understand de algorithm used to solve the problem, I can see that you are committing a few mistakes:
You're retrieving a multidimensional list element incorrectly, e.g., list_var[a][b] instead of list_var[b][a]. This can be solved in the for loops.
You're indexing variable colors this way: colors[end] = ..., but variable end is initialized as end = len(colors), i.e., with a value 1 unit greater than the maximum index allowed, remember that lists are zero-indexed.
A misplaced closing bracket.
Here's the corrected code. Run a file diff to see the changes I've made. I don't guarantee it now solves the problem you were given but the errors you came across are gone.
import random
def getvalidMatrix(length,width,colors):
map = dict()
for i in range(len(colors)):
map[colors[i]]=i
res = [[0] * length] * width
for i in range(width):
for j in range(length):
end = len(colors)-1
if i - 1 >= 0 and i - 2 >= 0 and res[i-1][j] == res[i-2][j]:
index = map[res[i-1][j]]
colors[index] = colors[end]
colors[end] = map[res[i-1][j]]
end -= 1
if j - 1 >= 0 and j - 2 >= 0 and res[i][j-1] == res[i][j-2]:
index = map[res[i][j-1]]
colors[index] = colors[end]
colors[end] = map[res[i][j-1]]
end -= 1
next=random.randint(0,end)
res[i][j] = colors[next]
return res
if __name__ == '__main__':
length = 3
width = 3
colors = [0,1,2]
print(getvalidMatrix(length, width, colors))
Related
so i need to find whats the longest sublist that can be mirrored, knowing the number of element
ex:
n = 5
my_list = [1,2,3,2,1]
heres my code:
n = int(input())
my_list = list(map(int, input().split()))
c = 0
s1 = my_list
x = 0
i = 0
while i < n:
s2 = s1[i:]
if s2 == s2[::-1]:
if c <= len(s2):
c = len(s2)
if i >= n-1:
i = 0
n = n - 1
s1 = s1[:-1]
i += 1
print(c)
as we see the list is the same when mirrored, but when n = 10 and my_list = [1,2,3,2,1,332,6597,6416,614,31] the result is 3 instead of the expected 5.
My solution would be splitting the array in each iteration into a left and a right array, and then reversing the left array.
Next, compare each element from each array and increment the length variable by one while the elements are the same.
def longest_subarr(a):
longest_exclude = 0
for i in range(1, len(a) - 1):
# this excludes a[i] as the root
left = a[:i][::-1]
# this also excludes a[i], needs to consider this in calculation later
right = a[i + 1:]
max_length = min(len(left), len(right))
length = 0
while(length < max_length and left[length] == right[length]):
length += 1
longest_exclude = max(longest_exclude, length)
# times 2 because the current longest is for the half of the array
# plus 1 to include to root
longest_exclude = longest_exclude * 2 + 1
longest_include = 0
for i in range(1, len(a)):
# this excludes a[i] as the root
left = a[:i][::-1]
# this includes a[i]
right = a[i:]
max_length = min(len(left), len(right))
length = 0
while(length < max_length and left[length] == right[length]):
length += 1
longest_include = max(longest_include, length)
# times 2 because the current longest is for the half of the array
longest_include *= 2
return max(longest_exclude, longest_include)
print(longest_subarr([1, 4, 3, 5, 3, 4, 1]))
print(longest_subarr([1, 4, 3, 5, 5, 3, 4, 1]))
print(longest_subarr([1, 3, 2, 2, 1]))
This covers test case for odd-length sub-array like [a, b, a] and even-length sub-array [a, b, b, a].
Since you need the longest sequence that can be mirrored, here is a simple O(n^2) approach for this.
Go to each index, consider it as the center, and expand towards both left and right, one step at a time, if the numbers are equal. Or else break, and move onto the next index.
def longest_mirror(my_array):
maxLength = 1
start = 0
length = len(my_array)
low = 0
high = 0
# One by one consider every character as center point of mirrored subarray
for i in range(1, length):
# checking for even length subarrays
low = i - 1
high = i
while low >= 0 and high < length and my_array[low] == my_array[high]:
if high - low + 1 > maxLength:
start = low
maxLength = high - low + 1
low -= 1
high += 1
# checking for even length subarrays
low = i - 1
high = i + 1
while low >= 0 and high < length and my_array[low] == my_array[high]:
if high - low + 1 > maxLength:
start = low
maxLength = high - low + 1
low -= 1
high += 1
return maxLength
I have this code where st is an array of a class that have x and y parameters. I have to sort their x or y. How can i reduce it so i dont have to write the same code 2 times (one for each case)?
def sort(st, coor):
for i in range(len(st)):
if coor == 'x':
selected = st[i]
j = i - 1
while j >= 0 and st[j].x > selected.x:
st[j + 1], st[j] = st[j], st[j + 1]
j -= 1
st[j + 1] = selected
i += 1
else:
selected = st[i]
j = i - 1
while j >= 0 and st[j].y > selected.y:
st[j + 1], st[j] = st[j], st[j + 1]
j -= 1
st[j + 1] = selected
i += 1
Extract a method for the code that is duplicated.
https://refactoring.guru/extract-method
In that new method, the part that is different is calling the x or y attribute of an instance, and this can be replaced by a call to getattr.
I've been working on this leetcode problem, which is essentially finding the number of valid paths in a maze given some obstacleGrid matrix. If obstacleGrid[i][j] == 1, then we have an obstacle at (i,j) and we have zero otherwise, which a valid spot. We can only move down and right with the goal of starting from the upper left to the bottom right.
I have written the code below:
def uniquePathsWithObstacles(self, obstacleGrid):
# obstruction at the start
if (obstacleGrid[0][0] == 1): return 0
# obstruction at the end
if (obstacleGrid[-1][-1] == 1): return 0
m, n = len(obstacleGrid), len(obstacleGrid[0])
memo = [[0] * n] * m
# starting move
memo[0][0] = 1
# now check the first row
for j in range(1, n):
memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
# now check the first column
for i in range(1, m):
memo[i][0] = 1 if (obstacleGrid[i][0] == 0 and memo[i-1][0] != 0) else 0
# now check everything else
for i in range(1, m):
for j in range(1, n):
if (obstacleGrid[i][j] == 1): memo[i][j] = 0
else: memo[i][j] = memo[i-1][j] + memo[i][j-1]
return memo[-1][-1]
I took the obvious DP approach and I know the idea works but something is wrong with the code; for some reason I don't think my memo matrix is being updated properly? I feel like the problem is staring at me in the face but for some reason I can't see it. Any help appreciated!
Edit: For obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] and if I had a print(memo) right before the return statement, I get [[1, 1, 2], [1, 1, 2], [1, 1, 2]]. This happens to give me the right answer, but the memo matrix is wrong!
One problem lies in the line memo = [[0] * n] * m.
This does not really create mcopies of the same list, but instead, it only creates the [0] * n list once and then creates memo as a list of m references to this list. Any change to any of these lists therefore modifies all other lists!
You can try this yourself:
memo = [[0] * 3] * 4
memo[0][1] = 1
print(memo)
This gives [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]].
Instead, you have to initialize each list on their own, e.g.,
memo = []
for i in range(m):
memo.append([0] * n)
I just tried to do this with recursion as an comparison rather than an answer.
import numpy as np
def number_of_paths(obstacles):
"""
Calculate the number of paths available in a maze with obstacles, with only right and down moves, from top left
to bottom right.
Args:
obstacles (ndarray): binary matrix with 1 representing obstacle
Returns:
int: the number of paths
"""
if obstacles[0,0] == 1:
raise ValueError # cannot start on an obstacle
count = 0
if obstacles.shape == (2,1):
return 1
if obstacles.shape == (1,2):
return 1
if obstacles.shape[1] > 1 and obstacles[0,1] == 0:
count += number_of_paths(obstacles[:,1:])
if obstacles.shape[0] > 1 and obstacles[1,0] == 0:
count += number_of_paths(obstacles[1:,:])
return count
your code is correct and 1 line must be updated per the below:
def uniquePathsWithObstacles(self, obstacleGrid):
# obstruction at the start
if (obstacleGrid[0][0] == 1): return 0
# obstruction at the end
if (obstacleGrid[-1][-1] == 1): return 0
m, n = len(obstacleGrid), len(obstacleGrid[0])
memo = [[0] * n for i in range(m)]
# starting move
memo[0][0] = 1
# now check the first row
for j in range(1, n):
#memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
# now check the first column
for i in range(1, m):
memo[i][0] = 1 if (obstacleGrid[i][0] == 0 and memo[i-1][0] != 0) else 0
# now check everything else
for i in range(1, m):
for j in range(1, n):
if (obstacleGrid[i][j] == 1): memo[i][j] = 0
else: memo[i][j] = memo[i-1][j] + memo[i][j-1]
return memo[-1][-1]
Following is the code where in caller is called first from another module,
centroids is of float type (an array of numberofcluster * numberoffeatures)
labels is 1d array of numberofexplanations
array is not getting updated
def caller(centroids, labels):
number_of_features = len(centroids[0])
one_column = [0, 0, 0, 0, 0]
i = 0
j = 0
array = [[0 for x in xrange(number_of_features)] for x in xrange(5)]
while i < number_of_features:
j = 0
while j < 5:
one_column[j] = centroids[j][i]
j += 1
rank(one_column, i, array)
i += 1
return calculatemean(number_of_features, array)
def rank(one_column, ithfeature, array):
temp_dict = {}
i = 0
while i < 5:
temp_dict[one_column[i]] = i
i += 1
number_of_uniquevalues = len(set(temp_dict))
sorted_dict = OrderedDict(sorted(temp_dict.items()))
i = 0
keys_list = sorted_dict.keys()
while i < 5:
array[one_column.index(keys_list[i])][ithfeature] = sorted_dict[keys_list[i]]
i += 1
I have referred to this link
Two dimensional array in python
and the issue is resolved
If I for example have an array:
A = (0,2,3,4,5,2,1,2,3,4,5,6,7,8,7,6,5,4,5,6)
It can be seen that there are 4 turning points. (at A[4],A[6], A[13], A[17])
How can I use python to return the number of turning points?
import numpy as np
import scipy.integrate as SP
import math
def turningpoints(A):
print A
N = 0
delta = 0
delta_prev = 0
for i in range(1,19):
delta = A[i-1]-A[i] #Change between elements
if delta < delta_prev: #if change has gotten smaller
N = N+1 #number of turning points increases
delta_prev = delta #set the change as the previous change
return N
if __name__ == "__main__":
A = np.array([0,2,3,4,5,2,1,2,3,4,5,6,7,8,7,6,5,4,5,6])
print turningpoints(A)
Currently, this system is flawed and certainly not very elegant. Any ideas?
If you have numpy:
def turningpoints(lst):
dx = np.diff(lst)
return np.sum(dx[1:] * dx[:-1] < 0)
Or the non-numpy equivalent version:
def turningpoints(lst):
dx = [x - y for x, y in zip(lst[1:], lst[:-1])]
return sum(dx1 * dx2 < 0 for dx1, dx2 in zip(dx[1:], dx[:-1]))
And just for the love of one-liners:
def turningpoints(lst):
return sum(x0*x1 + x1*x2 < x1*x1 + x0*x2 for x0, x1, x2 in zip(lst[2:], lst[1:-1], lst[:-2]))
But the readability is arguably decreased on this one :)
I know it's an old question, but I just had the same problem and as Cardin stated in the comments of Malvolio's answer, the answer cannot handle successive points with the same value like [1, 2, 3, 4, 4, 4, 3, 2, 1]. My implementation can handle this problem.
Although, it returns two lists with the indices of the minimum and maximum turning points.
def turning_points(array):
''' turning_points(array) -> min_indices, max_indices
Finds the turning points within an 1D array and returns the indices of the minimum and
maximum turning points in two separate lists.
'''
idx_max, idx_min = [], []
if (len(array) < 3):
return idx_min, idx_max
NEUTRAL, RISING, FALLING = range(3)
def get_state(a, b):
if a < b: return RISING
if a > b: return FALLING
return NEUTRAL
ps = get_state(array[0], array[1])
begin = 1
for i in range(2, len(array)):
s = get_state(array[i - 1], array[i])
if s != NEUTRAL:
if ps != NEUTRAL and ps != s:
if s == FALLING:
idx_max.append((begin + i - 1) // 2)
else:
idx_min.append((begin + i - 1) // 2)
begin = i
ps = s
return idx_min, idx_max
To correctly answer the question, the number of turning points is then computed as:
sum(len(x) for x in turning_points(X))
Example
You're overthinking it. A "turning point" is one that is either higher than the points on both sides, or lower.
def turningpoints(x):
N=0
for i in range(1, len(x)-1):
if ((x[i-1] < x[i] and x[i+1] < x[i])
or (x[i-1] > x[i] and x[i+1] > x[i])):
N += 1
return N
>>> turningpoints([0,2,3,4,5,2,1,2,3,4,5,6,7,8,7,6,5,4,5,6])
4
>>> def turns(L):
... answer, delta = 0, -1 if L[1]<L[0] else 1
... i = 2
... while i < len(L):
... d = -1 if L[i]<L[i-1] else 1
... if d != delta:
... answer += 1
... delta = d
... i += 1
... return answer
...
>>> L = [0,2,3,4,5,2,1,2,3,4,5,6,7,8,7,6,5,4,5,6]
>>> turns(L)
4
def group_in_threes(slicable):
for i in range(len(slicable)-2):
yield slicable[i:i+3]
def turns(L):
for index, three in enumerate(group_in_threes(L)):
if (three[0] > three[1] < three[2]) or (three[0] < three[1] > three[2]):
yield index + 1
>>> list(turns([0,2,3,4,5,2,1,2,3,4,5,6,7,8,7,6,5,4,5,6]))
[4, 6, 13, 17]
>>> len(_)
4