Transposing a nxn Matrix in Python using only for/while loops - python

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

Related

Get list for duplicates on an other list python

I need help to get a list from an other :
input :
[[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
output wanted :
[0, 0, 1, 0, 0, 1, 2, 3]
I tried to use enumerate but I fail, any suggestion ?
Edit : Every time I meet a new element in the list, I associate this new element with a number (start from 0 and +1 every new element) and if I recognize it later I put the same number, so [1,1] --> 0 because is the first element we met and [2,2] --> 1 etc...
Okay I found a solution :
One more thing before, my example is bad because I can have [1,2] in element of the list for input
the solution I found is
line = [[1, 1], [1, 1], [2, 2], [1, 1], [2, 1], [2, 2], [3, 3], [4, 4]]
p = []
line_not = []
k = 0
for i in range (len(line)):
if line[i] in line[:i]:
p.append(line_not[:k].index(line[i]))
else:
p.append(k)
line_not.append(line[i])
k+=1
the output is :
[0, 0, 1, 0, 2, 1, 3, 4]
If u have a better solution, tell me !
try to make a map, this works:
inp=[[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
out = [0, 0, 1, 0, 0, 1, 2, 3]
mymap={inp[0][0]:0}
output = [0]
k_count=1
for i in inp[1:]:
if i[0] in mymap.keys():
output.append(mymap[i[0]])
else:
mymap[i[0]] = k_count
output.append(mymap[i[0]])
k_count+=1
and then output == [0, 0, 1, 0, 0, 1, 2, 3]
First build a dictionary that does the assocation of each unique element with a number:
>>> x = [[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
>>> d = {}
>>> for [i, _] in x:
... if i not in d:
... d[i] = len(d)
...
and then you can easily build your output list by doing lookups in that dictionary:
>>> [d[i] for [i, _] in x]
[0, 0, 1, 0, 0, 1, 2, 3]
this would work in your current example, but it is not a comprehensive solution. Without context its hard to understand what you are trying to achieve, so use with care:
import numpy as np
inp = [[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
out = np.array([i[0] for i in inp]) - 1
print(out) # result: [0 0 1 0 0 1 2 3]

Creating dataframe from list of arrays (varying shapes)

I am trying to convert a list of arrays of varying shapes to a dataframe.
import numpy as np
import pandas as pd
data = [np.array([[1, 2], [1, 3], [1, 1]]),
np.array([[1, 2, 3], [3, 1, 2], [3, 2, 1]])]
names = ['A', 'B']
df = pd.DataFrame(data=data, columns=names)
df
However, this gives the error-
ValueError: Shape of passed values is (2, 1), indices imply (2, 2)
I then tried-
df = pd.DataFrame(np.array([None, *data], dtype=object)[1:]).T
df
0 1
0 [[1, 2], [1, 3], [1, 1]] [[1, 2, 3], [3, 1, 2], [3, 2, 1]]
Which is not my desired output.
I want each inner list in as separate rows, like the following:
A B
0 [1, 2] [1, 2, 3]
1 [1, 3] [3, 1, 2]
2 [1, 1] [3, 2, 1]
Not sure how to proceed.
Try:
pd.DataFrame(dict((k,list(v)) for k,v in zip(names, data)))
Output:
A B
0 [1, 2] [1, 2, 3]
1 [1, 3] [3, 1, 2]
2 [1, 1] [3, 2, 1]
Let us try concat , it will do it one by one sub-data
out = pd.concat([pd.Series(list(x)) for x in data], keys=names, axis=1)
A B
0 [1, 2] [1, 2, 3]
1 [1, 3] [3, 1, 2]
2 [1, 1] [3, 2, 1]
this is what worked for me, istead of sending the data as nasted lists i sended a dictionary which define its values for each column name, this way pandas didnt converted it to 3 columns:
data = [array([[1, 2],
[1, 3],
[1, 1]]),
array([[1, 2, 3],
[3, 1, 2],
[3, 2, 1]])]
names = ['A', 'B']
pd.DataFrame({name:l.tolist() for name,l in zip(names,data)})
Out[5]:
A B
0 [1, 2] [1, 2, 3]
1 [1, 3] [3, 1, 2]
2 [1, 1] [3, 2, 1]
the wrong way
pd.DataFrame(data)
>>>
0
0 [[1, 2], [1, 3], [1, 1]]
1 [[1, 2, 3], [3, 1, 2], [3, 2, 1]]
# or
pd.DataFrame([l.tolist() for l in data])
>>>
0 1 2
0 [1, 2] [1, 3] [1, 1]
1 [1, 2, 3] [3, 1, 2] [3, 2, 1]

variable access between Function calls behavior in Python

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.

python: assign and read out the values of a 2-d list [duplicate]

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)]

How to get this list of combinations?

I have two numbers, N and L (let's say 5 and 3).
How can I generate every possible list where the sum of the list is equal to N (5) and the length of every list is L (3)?
Example output (in this case):
[0, 0, 5]
[0, 1, 4]
[0, 2, 3]
[0, 3, 2]
...
[0, 5, 0]
...
[1, 4, 0]
...
[5, 0, 0]
I've checked out itertools and its combinations and permutations functions, but they don't seem right for the task.
You can create a recursive function to generate all possible permutations with the given conditions, and then filter to retain only the lists which sum to the desired value:
def list_results(a, b):
return [i for i in permutations(b) if sum(i) == a]
def permutations(d, current = []):
if len(current) == d:
yield current
else:
for i in range(10):
yield from permutations(d, current+[i])
print(list_results(5, 3))
Output:
[[0, 0, 5], [0, 1, 4], [0, 2, 3], [0, 3, 2], [0, 4, 1], [0, 5, 0], [1, 0, 4], [1, 1, 3], [1, 2, 2], [1, 3, 1], [1, 4, 0], [2, 0, 3], [2, 1, 2], [2, 2, 1], [2, 3, 0], [3, 0, 2], [3, 1, 1], [3, 2, 0], [4, 0, 1], [4, 1, 0], [5, 0, 0]]
Edit: a slightly faster would entail an additional check in the recursive function:
import time
def timeit(f):
def wrapper(*args, **kwargs):
c = time.time()
results = list(f(*args, **kwargs))
print("Result from function '{}' achieved in {}".format(f.__name__, abs(c-time.time())))
return results
return wrapper
#timeit
def outer_permutations():
def permutations1(d, b, current = []):
if len(current) == d:
yield current
else:
for i in range(10):
if len(current) < 2 or sum(current+[i]) == b:
yield from permutations1(d, b, current+[i])
yield from permutations1(3, 5)
#timeit
def list_results(a, b):
return [i for i in permutations(b) if sum(i) == a]
v = outer_permutations()
v1 = list_results(3, 5)
Output:
Result from function 'outer_permutations' achieved in 0.0006079673767089844
Result from function 'list_results' achieved in 0.09148788452148438
Note that the output from both functions is:
[[0, 0, 5], [0, 1, 4], [0, 2, 3], [0, 3, 2], [0, 4, 1], [0, 5, 0], [1, 0, 4], [1, 1, 3], [1, 2, 2], [1, 3, 1], [1, 4, 0], [2, 0, 3], [2, 1, 2], [2, 2, 1], [2, 3, 0], [3, 0, 2], [3, 1, 1], [3, 2, 0], [4, 0, 1], [4, 1, 0], [5, 0, 0]]

Categories

Resources