i do learn Python for scientific working. At the moment i try to generate a 10x10 random Matrix with binary entries: 0 and 1. I already got a solution with numpy BUT im interested of what is the error in my own solution.
The Idea is to Access every entry of my Matrix seperately and assign a value to it by calling random.randint(0, 1 ) within two while loops. In Advance i define a dummy 10x10 Matrix called "World" and reassign ist values it in the loop. The Code Looks how follows:
import random
World=list(10*[10*[0]]) #this is my dummy matrix
i=0
j=0
while i <= 9:
while j <= 9:
World[i][j]=random.randint(0, 1) #here i want to Access a specific element of my dummy Matrix and "overwrite" it
if j == 9:
j=0 #if the counter "j" reaches 9 - the last element - it shall assign j=0 and leave the innermost while loop by "break"
break
j=j+1
i=i+1
for x in World:
print(*x)
The Problem with the Output should be obvious:
columns are equal
I am hopefully u understand what was my Intention here and can help me fix my code. I tried many many Things but i did not fix this.
I already found a 2-line short solution which i will use in my final Code but i want to run this also on my own because i am convinced this could work also well.
Many Thanks in Advance.
- Wendel
Your error is in the creation of the list.
NOTE:
[0] * m returns just a reference to a list of m zeros, but not a list.
The subsequent repeating of this element creates a list of n items
that all reference to the same list (just as well as the operation b =
a for lists does not create the new list), so all rows in the
resulting list are actually the same string.
import random
#World=list(10*[10*[0]]) #this is my dummy matrix
n = 10
World= [0] * n
for i in range(n):
World[i] = [0] * n
i=0
j=0
while i <= 9:
while j <= 9:
World[i][j]=random.randint(0, 1) #here i want to Access a specific element of my dummy Matrix and "overwrite" it
if j == 9:
j=0 #if the counter "j" reaches 9 - the last element - it shall assign j=0 and leave the innermost while loop by "break"
break
j=j+1
i=i+1
for x in World:
print(*x)
Suppose that two numbers are given: the number of rows of n and the number of columns m. You must create a list of size n×m, filled with, say, zeros.
The obvious solution appears to be wrong:
a = [[0] * m] * n
This can be easily seen if you set the value of a[0][0] to 5, and then print the value of a[1][0] — it will also be equal to 5. The reason is, [0] * m returns just a reference to a list of m zeros, but not a list. The subsequent repeating of this element creates a list of n items that all reference to the same list (just as well as the operation b = a for lists does not create the new list), so all rows in the resulting list are actually the same string.
n = 3
m = 4
a = [[0] * m] * n
a[0][0] = 5
print(a[1][0])
A possible way: you can create a list of n elements (say, of n zeros) and then make each of the elements a link to another one-dimensional list of m elements:
n = 3
m = 4
a = [0] * n
for i in range(n):
a[i] = [0] * m
Another (but similar) way: create an empty list and then append a new element to it n times (this element should be a list of length m):
n = 3
m = 4
a = []
for i in range(n):
a.append([0] * m)
But the easiest way is to use generator, creating a list of n elements, each of which is a list of m zeros:
n = 3
m = 4
a = [[0] * m for i in range(n)]
In this case each element is created independently from the others. The list [0] * m is n times consructed as the new one, and no copying of references occurs.
Related
I have the following Matlab code (adopted from Programming and Numerical Methods in MATLAB by Otto&Denier, page 75)
clear all
p = input('Enter the power you require: ');
points = p+2;
n = 1:points;
for N = n
sums(N) = 0;
for j = 1:N
sums(N) = sums(N)+j^p;
end
end
The output for 3 as the given value of p is the following list
>> sums
sums =
1 9 36 100 225
I have written the following Python code (maybe not the most 'Pythonic way') trying to follow as much as possible Matlab instructions.
p = int(input('Enter the power you require: '))
points = p+2
n = range(points)
for N in range(1, len(n)+1):
sums = [0]*N
for index, item in list(enumerate(sums)):
sums[index] = item+index**p
Nevertheless the output is not same list. I have tried to replace the inner loop with
for j in range(1,N+1):
sums[N] = sums[N]+j**p
but this results to an index error message. Thanks in advance for any suggestions.
This might be due to the index difference. In Python, it starts from 0 while it's 1 in Matlab. Also, sums = [0]*N initialize a list of a length N, this has to be moved outside of the loop.
points = p+2
sums = [0]*points
for N in range(0, points):
for index in range(0, N+1):
sums[N] = sums[N] + (index+1)**p
sums(N) = 0; does not create an array of all zeros, it sets element N of the existing array to 0, and creates additional elements in the array if it not at least of length N.
Because N grows by one each iteration, you could initialize as an empty array before the loop, and append(0) inside the loop:
sums = []
for N in range(1, len(n)+1):
sums.append(0)
I don’t particularly like the use of enumerate here either, I would:
for index in range(N)
sums[index] += (index + 1)**p
(Notice the +1 on the index that was missing in the code in the OP!)
Finally, n is just confusing here. I would:
for N in range(1, points + 1):
…
I want that user give input like this
[[3,4,5],[7,2,1]]
and it will create a 2d array automatically and store in a. so when print(a) will given it returns
a=[[3,4,5],[7,2,1]]
where type(a[0][0]) i mean all elements inside a will be int. How can I do it?
Input:
2 // no.of rows
3 // no.of columns
1 2 3
4 5 6
Output:
[[1,2,3],[4,5,6]]
Solution:
r = int(input())
c = int(input())
a = [list(map(int,input().split())) for _ in range(r)]
print(a)
The variable c isn't used in the code, so you can simply get it as a string and also ignore the assignment using input()
Line 3 involves List Comprehension (documentation).
n = int(input())
m = int(input())
input_list = []
for i in range(n):
list1 = []
for j in range(m):
z = int(input())
list1.append(z)
input_list.append(list1)
print(input_list)
Okay so we take the size of the 2-d array from the user in n and m resp.
We create an empty list named as input_list.
Now we run a loop for n times so this will be the number of rows in the 2-d array.
for every row we create a list named as list1. Run a loop to take inputs from the user on the elements in the row.
Then we append the newly created row (list1) in the input_list.This action is performed for all the rows.
And when the execution finishes we get the input_list as a 2-d array.
Here is a Python code for finding maximum product we can get from 13 adjacent digits of a number. There is no error message, but this program is not giving the desired output. I am getting(in repl.it) 1 everytime, though it is clear that the answer is not 1. I am new to programming.
My attempt
I have converted the number into an string and stored it into a array to get element by element. The outer for loop traversing over all the numbers(last time when i have value len(n)-12, i+j will reach the last entry of the array. (Though the array stores the number in a reverse order, I haven't reversed it because, we don't need to).
n = "123899778978978787888787778788767677667"
arr = []
for i in range(len(n)):
arr.append(int(n)%10)
n = str(int(n)//10)
mul = 1
max_mult = 1
for i in range(len(n)-12):
for j in range(13):
mul = mul * int(arr[i+j])
if(max_mult<mul):
max_mult = mul
print(max_mult)
Can anyone tell me where I am going wrong? Any help will be appreciated.
Your logic can be simplified somewhat using zip:
n_list = list(map(int, list(n)))
res = max(i * j for i, j in zip(n_list, n_list[1:])) # 81
If you insist on using a for loop:
n_list = list(map(int, list(n)))
max_mult = 0
for i, j in zip(n_list, n_list[1:]):
mult = i * j
if mult > max_mult:
max_mult = mult
print(max_mult) # 81
Note you can modify your existing range-based iteration, but this is not considered Pythonic:
for i in range(len(n_list) - 1):
mult = n_list[i] * n_list[i+1]
if mult > max_mult:
max_mult = mult
Does anyone know why my index matrix[k][m]=sum/9 is out of range? I'm pretty sure that my solution is correct. I tried debugging it, but I still cannot think
why it's not working.
def downsample_by_3(image):
matrix_image = copy.deepcopy(image)
matrix=[ [], [], [] ]
k=0
m=0
for i in range(0,len(matrix_image),3):
for j in range(0,len(matrix_image[i]),3):
sum=0
for r in range(i,i+3):
for c in range(j,j+3):
sum+=matrix_image[r][c]
m+=1
matrix[k][m]=sum/9
m=0
k+=1
return matrix
The image is presented as a matrix (list of lists).
Let's say I took this list,
print(downsample_by_3([[2,2,2],[2,2,2],[2,2,2]]))
it should return a list with 18.
Another example of it to understand it better:
You have a list of empty lists. So while matrix[0] is fine, matrix[0][0] is out of bounds.
You have to either preallocate the lengths of the sublists beforehand if you wish to access them by index, or you append the averages as shown in Gary02127's answer. If you choose the former, you must also increment m after matrix[k][m]=sum/9.
However, your code has another out-of-bounds bug waiting to be triggered. Suppose you have a 3x4 image, i.e., one of the dimensions isn't divisible by 3. You average the first 3x3 block just fine, and then you try to access the pixels at column indices 3-5.
If your dimensions aren't divisible by the downsample factor, you have 3 choices:
raise an error at the beginning of the function call,
add extra rows/columns to make your matrix divisible by your factor (you can use the value of the last element of the row/column to extend it further), or
use only as many elements are you have left.
Here's an implementation with approach #3 and preallocating your matrix.
def downsample(image, factor):
height = len(image)
# this assumes that all sublists have the same length!
width = len(image[0])
matrix = [[None] * ((width + factor - 1) // factor)
for _ in range((height + factor - 1) // factor)]
k = 0
m = 0
for i in range(0, height, factor):
for j in range(0, width, factor):
# don't overshadow the `sum` builtin
total = 0
count = 0
for r in range(i, min(i+factor, height)):
for c in range(j, min(j+factor, width)):
total += image[r][c]
count += 1
matrix[k][m] = total / count
m += 1
m = 0
k += 1
return matrix
You start with matrix hard-coded to a sequence of empty lists matrix=[ [], [], [] ], and then in the
matrix[k][m]=sum/9
line, you try to force a value into one of those slots, but there are no slots. The k will be okay for the first few (from 0 through 2), but the m is going to error right away. Seems like you need to dynamically create matrix on the fly. Maybe
matrix[k].append(sum/9)
Also, a return matrix at the end your function wouldn't hurt. :)
The above should help you move forward. At least it gives running code.
I have a 2d array with a different species in each one. I pick a random element on the array and I want to count up how many of each species are in the eight squares immediately adjacent to that element.
But I want the array to wrap at the edges, so if I pick an element on the top row, the bottom row will be counted as "adjacent". How can I do this while iterating through j in range (x-1,x+1) and the same for j and y?
Also, is there a more elegant way of omitting the element I originally picked while looking through the adjacent squares than the if (j!=x or k!=y line?
numspec = [0] * len(allspec)
for i in range (0,len(allspec)):
#count up how many of species i there is in the immediate area
for j in range(x-1,x+1):
for k in range(y-1,y+1):
if (j!=x or k!=y):
numspec[hab[i][j]] = numspec[hab[i][j]]+1
You can wrap using j%8 that gives you a number from 0 to 7.
As for wrapping, I would recomend using relative indexing from -1 to +1 and then computing real index using modulo operator (%).
As for making sure you don't count the original element (x, y), you are doing just fine (I would probably use reversed contidion and continue, but it doesn't matter).
I don't quite understand your usage of i, j, k indexes, so I'll just assume that i is index of the species, j, k are indexes into the 2d map called hab which I changed to x_rel, y_rel and x_idx and y_idx to make it more readable. If I'm mistaken, change the code or let me know.
I also took the liberty of doing some minor fixes:
introduced N constant representing number of species
changed range to xrange (xrange is faster, uses less memory, etc)
no need to specify 0 in range (or xrange)
instead of X = X + 1 for increasing value, I used += increment operator like this: X += 1
Here is resulting code:
N = len(allspec)
numspec = [0] * N
for i in xrange(N):
for x_rel in xrange(-1, +1):
for y_rel in xrange(-1, +1):
x_idx = (x + xrel) % N
y_idx = (y + yrel) % N
if x_idx != x or y_idx != y:
numspec[hab[x_idx][y_idx]] += 1
You could construct a list of the adjacent elements and go from there. For example if your 2d list is called my_array and you wanted to examine the blocks immediately surrounding my_array[x][y] then you can do something like this:
xmax = len(my_array)
ymax = len(my_array[0]) #assuming it's a square...
x_vals = [i%xmax for i in [x-1,x,x+1]]
y_vals = [blah]
surrounding_blocks = [
my_array[x_vals[0]][y_vals[0]],
my_array[x_vals[0]][y_vals[1]],
my_array[x_vals[0]][y_vals[2]],
my_array[x_vals[2]][y_vals[0]],
my_array[x_vals[2]][y_vals[1]],
my_array[x_vals[2]][y_vals[2]],
my_array[x_vals[1]][y_vals[0]],
my_array[x_vals[1]][y_vals[2]],
]