Related
When I need to add two 2D lists element wise, the approach I am using is
l1 = [[1, 1, 1],
[2, 2, 2],
[3, 3, 3]]
l2 = [[1, 1, 1],
[2, 2, 2],
[3, 3, 3]]
new = list(map(lambda e: [sum(x) for x in zip(*e)], zip(l1, l2)))
print(new)
output : [[2, 2, 2],
[4, 4, 4],
[6, 6, 6]]
This code is already difficult to read.
So how would I add two n dimensional lists element wise? Is there a pythonic way to do it or should I use numpy?
So say I have a list sequences such as this.
I want to remove all sequences where its total sum = N and/or it has a contiguous subarray with sum = N.
For example, if N = 4, then (1,1,2) is not valid since its total is 4. (1,1,3) is also not valid since the (1,3) is also 4. (1,3,1) is also not valid for the same reason.
lst = [
(1,1,1), (1,1,2), (1,1,3),
(1,2,1), (1,2,2), (1,2,3),
(1,3,1), (1,3,2), (1,3,3),
(2,1,1), (2,1,2), (2,1,3),
(2,2,1), (2,2,2), (2,2,3),
(2,3,1), (2,3,2), (2,3,3),
(3,1,1), (3,1,2), (3,1,3),
(3,2,1), (3,2,2), (3,2,3),
(3,3,1), (3,3,2), (3,3,3)
]
E.g.
Input: 4 3
Output: 2 1 2
So what I have right now is
lst = [t for t in list(product(range(1,n),repeat=n-1)) if not any((sum(t[l:h+1]) % n == 0) for l, h in combinations(range(len(t)), 2))]
Currently it is in O(n2) if I'm not mistaken. What would be a better way to do this?
If you can use numpy, you can concatenate the total sum of each tuple with the contiguous value sums, then check if any of your resultign elements are equal to 4:
arr = np.array(lst)
arr[~(np.concatenate((np.sum(arr,axis=1).reshape(-1,1),
(arr[:,:-1]+ arr[:,1:])),axis=1) == 4).any(1)]
# or:
arr[(np.concatenate((np.sum(arr,axis=1).reshape(-1,1),
(arr[:,:-1]+ arr[:,1:])),axis=1) != 4).all(1)]
Returning:
array([[1, 1, 1],
[1, 2, 3],
[2, 1, 2],
[2, 3, 2],
[2, 3, 3],
[3, 2, 1],
[3, 2, 3],
[3, 3, 2],
[3, 3, 3]])
I need to generate a list of lists in that special way:
[3, 1, 4] -> [[1, 2, 3], [1], [1, 2, 3, 4]]
That means that every list in a list of lists must be in range of the given list values. I've tried smth like:
L = [3, 1, 4]
q = [i for i in L]
print(list([x] for x in range(y for y in q)))
But it return a TypeError: generator cannot be interpreted as an integer
That all has to be a single generator expression.
Using a list comprehension.
Try:
L = [3, 1, 4]
print([list(range(1, i+1)) for i in L])
Output:
[[1, 2, 3], [1], [1, 2, 3, 4]]
I am try to code a game which has a 3x3 grid (think noughts & crosses [US=Tic Tac Toe]).
Each cell has a weighting. When the player places a counter a score is calculated. I want my code to go through the 3x3 matrix and find the top score and return the co-ordinates of the cell where that top score is found (this works) - but if there are several cells with an equal top score I want to return a list containing each of the places where that score is found.
Here is a cut-down version of my code (with LOTS of print statements to try to work out why it's not working).
The intention is that the loop records a simple list ("pos") which has the row and column co-ordinates (e.g. [0][2]) and appends this to a running list of equal scores ("possibles")
If instead of trying to append a 2-entry list I put in a single random number, the overall list ("possibles") builds as expected, but appending the 2-entry list results in a duplicated list of the final position (see output).
I clearly have a logic problem, but I am new to Python. Can anyone show me where I have gone wrong?
def test():
val = 1
max_val = 0
possibles = [] # This is the list where I will store a list of equally weighted positions
pos = [] # This is simply a 2 number co-ordinate
pos.append("") # Get it ready for row & col references
pos.append("")
for row in range (0,3):
for col in range (0,3):
print("Testing row",row,"col",col)
print("Possibles so far",possibles)
print("Pos=",pos)
pos[0] = row
pos[1] = col
print("Now pos=",pos)
#possibles.append(randint(0,100)) # This works
possibles.append(pos) # This doesn't
print("List of equals",possibles)
test()
Output:
Testing row 0 col 0
Possibles so far []
Pos= ['', '']
Now pos= [0, 0]
Testing row 0 col 1
Possibles so far [[0, 0]]
Pos= [0, 0]
Now pos= [0, 1]
Testing row 0 col 2
Possibles so far [[0, 1], [0, 1]]
Pos= [0, 1]
Now pos= [0, 2]
Testing row 1 col 0
Possibles so far [[0, 2], [0, 2], [0, 2]]
Pos= [0, 2]
Now pos= [1, 0]
Testing row 1 col 1
Possibles so far [[1, 0], [1, 0], [1, 0], [1, 0]]
Pos= [1, 0]
Now pos= [1, 1]
Testing row 1 col 2
Possibles so far [[1, 1], [1, 1], [1, 1], [1, 1], [1, 1]]
Pos= [1, 1]
Now pos= [1, 2]
Testing row 2 col 0
Possibles so far [[1, 2], [1, 2], [1, 2], [1, 2], [1, 2], [1, 2]]
Pos= [1, 2]
Now pos= [2, 0]
Testing row 2 col 1
Possibles so far [[2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0]]
Pos= [2, 0]
Now pos= [2, 1]
Testing row 2 col 2
Possibles so far [[2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1]]
Pos= [2, 1]
Now pos= [2, 2]
List of equals [[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]]
You append the same object pos over and over again to your list. If you change its value in the next loop, all its representations are changed as well. You can test this. Append at the end of your test function:
for item in possibles:
print(item, id(item))
See, all list items have the same id.
To avoid this, assign a new object in each loop:
def test():
possibles = []
for row in range (3):
for col in range (3):
pos = [row, col] #create a new list
print("Now pos=",pos)
possibles.append(pos) #and append this new element
print("List of equals",possibles)
test()
It looks similar, but instead of changing element [0] and [1] of an existing list pos, now in each loop a new list is created. If you check it with id(item) from above, all list elements of possibles have now a different id.
I have a nested list:
x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
I want to iterate over the list and return a new nested list with each list returned with one value missing. So:
new_x = [[2,3,4],[1,3,4],[1,2,4],[1,2,3]]
I have this:
temp_list = []
y = 0
for i in x:
temp_list += i.remove(y)
y+=1
print(x)
But what's happening is each iteration is removing the indexed item so the list goes out of range.
list = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
for count, i in enumerate(list):
if len(i) > 0:
del i[count]
print(list)
For each sublist it deletes the element with an index equal to the index of the sublist
>>>[[2, 3, 4], [1, 3, 4], [1, 2, 4], [1, 2, 3]]
Hope this helps!
You have to use pop instead for remove. See this one:
In [46]: x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
In [47]: new_list = [lst for ind, lst in enumerate(x) if lst.pop(ind)]
In [48]: new_list
Out[48]: [[2, 3, 4], [1, 3, 4], [1, 2, 4], [1, 2, 3]]
x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
for i in range(0,len(x)):
for j in range (0,len(x)):
if(i==j):
del(x[i][j])
print(x)
new_x = [[2,3,4],[1,3,4],[1,2,4],[1,2,3]]
del(x[i][j]) is used to delete by index from list