I am doing recursion and storing the value in every step if calling.
Like if my working program-code is like-
lst=[]
def after_occurance(ls,l,curr):
for i in range(l,curr):
if ls[i]==ls[curr]:
return False
return True
def permutate(A,l,r):
if l==r:
ans=A.copy()
print(A,ans)
# change the commenting of the following 2 lines to see the difference
lst.append(A)
#lst.append(ans)
print(lst)
return lst
else:
for i in range(l,r+1):
if after_occurance(A,l,i):
A[i],A[l] = A[l],A[i]
permutate(A,l+1,r)
hm[A[l]]=1
A[l],A[i] = A[i],A[l]
else:
continue
lst.clear()
A=[1,2,6]
A=sorted(A)
permutate(A,0,len(A)-1)
return lst
Following are 2 kind of outputs when Toggling between 2 commented line respectively
[1, 2, 6] [1, 2, 6]
[[1, 2, 6]]
[1, 6, 2] [1, 6, 2]
[[1, 2, 6], [1, 6, 2]]
[2, 1, 6] [2, 1, 6]
[[1, 2, 6], [1, 6, 2], [2, 1, 6]]
[2, 6, 1] [2, 6, 1]
[[1, 2, 6], [1, 6, 2], [2, 1, 6], [2, 6, 1]]
[6, 2, 1] [6, 2, 1]
[[1, 2, 6], [1, 6, 2], [2, 1, 6], [2, 6, 1], [6, 2, 1]]
[6, 1, 2] [6, 1, 2]
[[1, 2, 6], [1, 6, 2], [2, 1, 6], [2, 6, 1], [6, 2, 1], [6, 1, 2]]
[1 2 6 ] [1 6 2 ] [2 1 6 ] [2 6 1 ] [6 1 2 ] [6 2 1 ]
[1, 2, 6] [1, 2, 6]
[[1, 2, 6]]
[1, 6, 2] [1, 6, 2]
[[1, 6, 2], [1, 6, 2]]
[2, 1, 6] [2, 1, 6]
[[2, 1, 6], [2, 1, 6], [2, 1, 6]]
[2, 6, 1] [2, 6, 1]
[[2, 6, 1], [2, 6, 1], [2, 6, 1], [2, 6, 1]]
[6, 2, 1] [6, 2, 1]
[[6, 2, 1], [6, 2, 1], [6, 2, 1], [6, 2, 1], [6, 2, 1]]
[6, 1, 2] [6, 1, 2]
[[6, 1, 2], [6, 1, 2], [6, 1, 2], [6, 1, 2], [6, 1, 2], [6, 1, 2]]
[1 2 6 ] [1 2 6 ] [1 2 6 ] [1 2 6 ] [1 2 6 ] [1 2 6 ]
Can somebody explain this behavior and what basic rule should I follow while doing Recursive calls and variable access in python?
So, this is the code you really wanted to post:
def after_occurance(ls, l, curr):
for i in range(l, curr):
if ls[i] == ls[curr]:
return False
return True
def permutate(A, l, r):
if l == r:
ans = A.copy()
# change the commenting of the following 2 lines to see the difference
#lst.append(A)
lst.append(ans)
return
else:
for i in range(l, r + 1):
if after_occurance(A, l, i):
A[i],A[l] = A[l],A[i]
permutate(A, l + 1, r)
A[l],A[i] = A[i],A[l]
else:
continue
lst = []
A = [1,2,6]
A = sorted(A)
permutate(A, 0, len(A) - 1)
print(lst)
The difference comes from appending a copy() of A or just a reference to A.
When you append a reference to A, all the future changes to A show up in lst because the result is lst = [A, A, A, A, A, ....] and so lst cannot be anything apart from a list of the same thing.
When you append a copy() of A, you make a new list which is not changed after the append() and so records the history of how A looked over time.
Related
I want to know how to convert this: array([0, 1, 2, 3, 4, 5]) to this:
array([[0, 0, 0],
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]])
In short, given a flat array, repeat each element inside the array n times, so that each element creates a sub-array of n of the same element, and concatenate these sub-arrays into one, so that each row contains an element from the original array repeated n times.
I can do this:
def repeat(lst, n):
return [[e]*n for e in lst]
>repeat(range(10), 4)
[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
[4, 4, 4, 4],
[5, 5, 5, 5],
[6, 6, 6, 6],
[7, 7, 7, 7],
[8, 8, 8, 8],
[9, 9, 9, 9]]
How to do this in NumPy?
You can use numpy's repeat like this:
np.repeat(range(10), 4).reshape(10,4)
which gives:
[[0 0 0 0]
[1 1 1 1]
[2 2 2 2]
[3 3 3 3]
[4 4 4 4]
[5 5 5 5]
[6 6 6 6]
[7 7 7 7]
[8 8 8 8]
[9 9 9 9]]
You can use tile that handles dimensions:
a = np.array([0, 1, 2, 3, 4, 5])
N = 4
np.tile(a[:,None], (1, N))
# or
np.tile(a, (N, 1)).T
or broadcast_to:
np.broadcast_to(a, (N, a.shape[0])).T
# or
np.broadcast_to(a[:,None], (a.shape[0], N))
Or multiply by an array of ones:
a[:,None]*np.ones(N, dtype=a.dtype)
output:
array([[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
[4, 4, 4, 4],
[5, 5, 5, 5]])
I want duplicate rows in numpy arrays based on the numeric value of the first entry in each row. So if the value is 1, then the row isn't duplicated, but if the value is 3 that row will be represented 3 times. I tried to use np.repeat and np.tile but I don't know if they're the right tool for this and I haven't figured out if there is a way to do it yet.
Here are my randomly generated arrays :
[[[3 1 3 1 2]
[4 4 4 2 0]
[3 4 4 4 0]
[1 4 3 3 0]]
[[4 2 0 2 1]
[2 1 2 0 3]
[4 1 3 4 3]
[2 3 2 0 0]]]
My goal is to end up with this:
[[[3 1 3 1 2]
[3 1 3 1 2]
[3 1 3 1 2]
[4 4 4 2 0]
[4 4 4 2 0]
[4 4 4 2 0]
[4 4 4 2 0]
[3 4 4 4 0]
[3 4 4 4 0]
[3 4 4 4 0]
[1 4 3 3 0]]
[[4 2 0 2 1]
[4 2 0 2 1]
[4 2 0 2 1]
[4 2 0 2 1]
[2 1 2 0 3]
[2 1 2 0 3]
[4 1 3 4 3]
[4 1 3 4 3]
[4 1 3 4 3]
[4 1 3 4 3]
[2 3 2 0 0]
[2 3 2 0 0]]]
Here is the code I have so far
array = np.random.randint(5, size = (2, 4,5))
for a in array:
for b in a:
array = np.tile(a, (b[0],1))
If I print b[0], I can get each value. I want to use those values to duplicate each row.
3
4
3
1
4
2
4
2
So I thought I could loop through those values and multiply each row by its corresponding value to add new rows, but my result only duplicates the second array one time.
[[4 2 0 2 1]
[2 1 2 0 3]
[4 1 3 4 3]
[2 3 2 0 0]
[4 2 0 2 1]
[2 1 2 0 3]
[4 1 3 4 3]
[2 3 2 0 0]]
Where am I going wrong? Should I not use np.tile?
Since there is no guarantee that your original 2D sub-arrays in the 3D source array will have the same shape after performing this operation, they cannot in general be stacked back into a 3D array.
You can get a list of arrays with np.repeat by passing the first column of each 2D array as the number of repeats. It will then repeat each row the corresponding number of times:
from pprint import pprint
result = ([np.repeat(a[i], a[i, :, 0], axis=0) for i in range(a.shape[0])])
pprint(result)
Output:
[array([[3, 1, 3, 1, 2],
[3, 1, 3, 1, 2],
[3, 1, 3, 1, 2],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[3, 4, 4, 4, 0],
[3, 4, 4, 4, 0],
[3, 4, 4, 4, 0],
[1, 4, 3, 3, 0]]),
array([[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[2, 1, 2, 0, 3],
[2, 1, 2, 0, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[2, 3, 2, 0, 0],
[2, 3, 2, 0, 0]])]
Use numpy.repeat with np.arange:
import numpy as np
arr = np.array([[[3, 1, 3, 1, 2],
[4, 4, 4, 2, 0],
[3, 4, 4, 4, 0],
[1, 4, 3, 3, 0]],
[[4, 2, 0, 2, 1],
[2, 1, 2, 0, 3],
[4, 1, 3, 4, 3],
[2, 3, 2, 0, 0]]])
arr2d = np.vstack(arr)
dup = arr2d[np.repeat(np.arange(arr2d.shape[0]), arr2d[:,0])]
np.split(dup, np.cumsum(np.sum(np.split(arr2d[:,0], arr.shape[0]), 1)))[:-1]
Output:
[array([[3, 1, 3, 1, 2],
[3, 1, 3, 1, 2],
[3, 1, 3, 1, 2],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[3, 4, 4, 4, 0],
[3, 4, 4, 4, 0],
[3, 4, 4, 4, 0],
[1, 4, 3, 3, 0]]),
array([[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[2, 1, 2, 0, 3],
[2, 1, 2, 0, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[2, 3, 2, 0, 0],
[2, 3, 2, 0, 0]])]
Since the 2d-arrays do not always have same shape, most of the time it will yield list of arrays. Such inconsistency is not so well handled by numpy.
In such case, you can simply use itertools.repeat with list comprehension. (Though it looks quite similar to #gmds' answer)
Given l:
import itertools
l = [[[3, 1, 3, 1, 2], [4, 4, 4, 2, 0], [3, 4, 4, 4, 0], [1, 4, 3, 3, 0]],
[[4, 2, 0, 2, 1], [2, 1, 2, 0, 3], [4, 1, 3, 4, 3], [2, 3, 2, 0, 0]]]
[[j for i in sub for j in itertools.repeat(i, i[0])] for sub in l]
Output:
[[[3, 1, 3, 1, 2],
[3, 1, 3, 1, 2],
[3, 1, 3, 1, 2],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[4, 4, 4, 2, 0],
[3, 4, 4, 4, 0],
[3, 4, 4, 4, 0],
[3, 4, 4, 4, 0],
[1, 4, 3, 3, 0]],
[[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[4, 2, 0, 2, 1],
[2, 1, 2, 0, 3],
[2, 1, 2, 0, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[4, 1, 3, 4, 3],
[2, 3, 2, 0, 0],
[2, 3, 2, 0, 0]]]
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 4 years ago.
Here is a snippet of python code:
a = [[0]*3]*4
for i in range(4):
for j in range(3):
a[i][j] = i+j
print(a[i][j])
print(a)
However, the outputs of the two prints are different.
The former one prints what I want. And the second prints all the same for the 4 sublists.
It seems the problem of shallow copying. I really don't understand how and why it happens.
Update:
After I have solved this, I found another problem:
a = [[0]*3]*4
for i in range(4):
a[i] = [i, 2*i, 3*i]
The result is also what I want. I'm once again confused about this.
Who can tell me the difference?
a = [[0]*3]*4
for i in range(4):
for j in range(3):
a[i][j] = i+j
print(a)
print(a[i][j])//show the execution at every step
print(a)
At each step the list with same column is updated with the same value.
output is
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
0
[[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]]
1
[[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]]
2
[[1, 1, 2], [1, 1, 2], [1, 1, 2], [1, 1, 2]]
1
[[1, 2, 2], [1, 2, 2], [1, 2, 2], [1, 2, 2]]
2
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
3
[[2, 2, 3], [2, 2, 3], [2, 2, 3], [2, 2, 3]]
2
[[2, 3, 3], [2, 3, 3], [2, 3, 3], [2, 3, 3]]
3
[[2, 3, 4], [2, 3, 4], [2, 3, 4], [2, 3, 4]]
4
[[3, 3, 4], [3, 3, 4], [3, 3, 4], [3, 3, 4]]
3
[[3, 4, 4], [3, 4, 4], [3, 4, 4], [3, 4, 4]]
4
[[3, 4, 5], [3, 4, 5], [3, 4, 5], [3, 4, 5]]
5
[[3, 4, 5], [3, 4, 5], [3, 4, 5], [3, 4, 5]]
The multiplier of operator taking a list and an int will make makes shallow copies of the elements of the list, so you're on the right track.
Initialise like this instead
a = [[0] * 3 for _ in range(4)]
Here is the combination / permutator generator function that uses any number of lists with values and any length of template strings. The generator creates corresponding lists with combinations / permutations of values matching the template string.
The answer was given by a colleague here: https://stackoverflow.com/a/48121777/8820330
from itertools import permutations, combinations, product
def groups(sources, template, mode='P'):
func = permutations if mode == 'P' else combinations
keys = sources.keys()
combos = [func(sources[k], template.count(k)) for k in keys]
for t in product(*combos):
d = {k: iter(v) for k, v in zip(keys, t)}
yield [next(d[k]) for k in template]
# tests
sources = {
'a': [0, 1, 2],
'b': [3, 4, 5],
'c': [6, 7, 8],
}
templates = 'aa', 'abc', 'abba', 'cab'
for template in templates:
print('\ntemplate', template)
for i, t in enumerate(groups(sources, template, mode='C'), 1):
print(i, t)
Output:
template aa
1 [0, 1]
2 [0, 2]
3 [1, 2]
template abc
1 [0, 3, 6]
2 [0, 3, 7]
3 [0, 3, 8]
4 [0, 4, 6]
5 [0, 4, 7]
6 [0, 4, 8]
7 [0, 5, 6]
8 [0, 5, 7]
9 [0, 5, 8]
10 [1, 3, 6]
11 [1, 3, 7]
12 [1, 3, 8]
13 [1, 4, 6]
14 [1, 4, 7]
15 [1, 4, 8]
16 [1, 5, 6]
17 [1, 5, 7]
18 [1, 5, 8]
19 [2, 3, 6]
20 [2, 3, 7]
21 [2, 3, 8]
22 [2, 4, 6]
23 [2, 4, 7]
24 [2, 4, 8]
25 [2, 5, 6]
26 [2, 5, 7]
27 [2, 5, 8]
template abba
1 [0, 3, 4, 1]
2 [0, 3, 5, 1]
3 [0, 4, 5, 1]
4 [0, 3, 4, 2]
5 [0, 3, 5, 2]
6 [0, 4, 5, 2]
7 [1, 3, 4, 2]
8 [1, 3, 5, 2]
9 [1, 4, 5, 2]
template cab
1 [6, 0, 3]
2 [7, 0, 3]
3 [8, 0, 3]
4 [6, 0, 4]
5 [7, 0, 4]
6 [8, 0, 4]
7 [6, 0, 5]
8 [7, 0, 5]
9 [8, 0, 5]
10 [6, 1, 3]
11 [7, 1, 3]
12 [8, 1, 3]
13 [6, 1, 4]
14 [7, 1, 4]
15 [8, 1, 4]
16 [6, 1, 5]
17 [7, 1, 5]
18 [8, 1, 5]
19 [6, 2, 3]
20 [7, 2, 3]
21 [8, 2, 3]
22 [6, 2, 4]
23 [7, 2, 4]
24 [8, 2, 4]
25 [6, 2, 5]
26 [7, 2, 5]
27 [8, 2, 5]
As you can see, the generator supports strings of templates built of single characters. However, I am interested in how to transform the above generator, to support the templates' strings, for example in this form:
sources = {
'a1' = [0,1,2],
'a2' = [3,4,5],
'a3' = [6,7,8],
}
templates = 'a1a2a3'
It seems to me that the problem lies in the iteration of the string from templates, where the iteration runs after the individual elements. In my case, however, iteration would have to follow pairs from a given string. How can this be done?
Define your templates like this:
sources = {
'a1': [0, 1, 2],
'a2': [3, 4, 5],
'a3': [6, 7, 8],
}
templates = [['a1', 'a2', 'a3']]
And then it will work out of the box. The reason this works is that strings in python are in fact just lists of characters, so instead of defining 'abc' you could define ['a', 'b', 'c'] and this behaves the same in most situations.
I wanted to know why the solution I have written doesn't work:
def transpose(sudoku):
n = len(sudoku)
l_tr = [0]*n
k = 0
tr_sudoku = [0]*n
while k < n:
tr_sudoku[k] = l_tr
k = k+1
i = 0
for i in range(len(sudoku)):
j = 0
for j in range(len(sudoku)):
tr_sudoku[i][j] = sudoku[j][i]
print j, i, tr_sudoku, sudoku[i][j]
print tr_sudoku
return tr_sudoku
correct = [[1,2,3],[2,3,1],[3,1,2]]
print transpose(correct)
It outputs the following incorrect solution:
0 0 [[1, 0, 0], [1, 0, 0], [1, 0, 0]] 1
1 0 [[1, 2, 0], [1, 2, 0], [1, 2, 0]] 2
2 0 [[1, 2, 3], [1, 2, 3], [1, 2, 3]] 3
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
0 1 [[2, 2, 3], [2, 2, 3], [2, 2, 3]] 2
1 1 [[2, 3, 3], [2, 3, 3], [2, 3, 3]] 3
2 1 [[2, 3, 1], [2, 3, 1], [2, 3, 1]] 1
[[2, 3, 1], [2, 3, 1], [2, 3, 1]]
0 2 [[3, 3, 1], [3, 3, 1], [3, 3, 1]] 3
1 2 [[3, 1, 1], [3, 1, 1], [3, 1, 1]] 1
2 2 [[3, 1, 2], [3, 1, 2], [3, 1, 2]] 2
[[3, 1, 2], [3, 1, 2], [3, 1, 2]]
[[3, 1, 2], [3, 1, 2], [3, 1, 2]]
Help would be appreciated! Thanks.
The ideal correct solution to:
correct = [[1,2,4],[2,3,4],[3,4,2]]
would be:
tr_correct = [[1,2,3],[2,3,4],[4,4,2]]
You can easily transpose with zip:
def transpose(sudoku):
return list(map(list, zip(*sudoku)))
Example output:
>>> correct = [[1,2,3],[2,3,1],[3,1,2]]
>>> transpose(correct)
[[1, 2, 3], [2, 3, 1], [3, 1, 2]]
The easiest "manual" way is to switch rows and columns:
def transpose_manually(sudoku):
output = sudoku[:] # new grid the same size
for r in range(len(sudoku)): # each row
for c in range(len(sudoku[0])): # each column
output[c][r] = sudoku[r][c] # switch
return output