Python Forum

Full Version: Matrix understanding in Python
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi,
this is text of exercise:
Quote:Given a 2D grid, each cell is either a zombie 1 or a human 0. Zombies can turn adjacent (up / down / left / right) human beings into zombies every hour. Find out how many hours does it take to infect all humans?
I haven't found many resources on the 2d matrices in python ,so
I tried to break it down by thinking if I had a list rather than a matrix:
if I had only one list and had to change the element with a value of 0 to 1 I found this solution that works and returns a list with all the values ​​1

a = [0,1,1,0,1]
contagion = [1 if x == 0 else x for x in a]
print(contagion)
It also works for others (I did the tests)

But how do I get a matrix and then "calculate" how long it takes for it to become all of them?
(Nov-13-2019, 11:35 AM)RavCOder Wrote: [ -> ]But how do I get a matrix and then "calculate" how long it takes for it to become all of them?

I think that your code don't do what is expected in this assignment.

In order to calculate hours you loop over matrix until there all only zombies. How many loops, so many hours.
I know it's not correct, but doing nested loops without knowing what I should be looping is difficult
You can use numpy to create your 2D array, or perhaps a bit easier is an array of arrays.
So, assume a 10 by 10 array. Build it by creating a 10 element list, and append that list to your array 10 times creating 10 rows. You then access each row and column as ary[row][col].
Now, you need to avoid a gotcha. When appending each row to your array, you need a copy of that list, otherwise you can end up with 10 references to the same list.
Done this a couple times as early projects, once making the board for Conway's Game of Life and once for making the board for a Sudoku solver.
Looping of matrix is simple. Some examples:

>>> m = [[1, 0, 0, 0, 1], 
...      [0, 0, 0, 0, 0], 
...      [0, 1, 0, 0, 0], 
...      [0, 1, 0, 0, 0]]
>>> for row in m: 
...     print(row) 
...                                                                                        
[1, 0, 0, 0, 1]
[0, 0, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
>>> for col in zip(*m): 
...     print(col) 
...                                                                                        
(1, 0, 0, 0)
(0, 0, 1, 1)
(0, 0, 0, 0)
(0, 0, 0, 0)
(1, 0, 0, 0)  
Your actual problem is how to change values adjacent to zombie values. As this includes next/previous rows you should figure out when to make 'infection' happen.
I think about when scrolling through the list finds the number 0 and make it number 1, but my problem is how do I scroll an array of an array. the indexes I think are just the lists of matrix.
 matrix =   [[1, 0, 0, 0, 1], # matrix[0] index
             [0, 0, 0, 0, 0], # matrix[1] index
             [0, 1, 0, 0, 0], # matrix[2] index
             [0, 1, 0, 0, 0]] # matrix[3] index
I should do something like that (I know my logic is wrong and my syntax is also)
for i in zip(*list_zombies_human):
  print(i)

for j , n in i:
  if j == 1:
    i[n] = 0
print(j)
Task is described as:

Quote:Given a 2D grid, each cell is either a zombie 1 or a human 0. Zombies can turn adjacent (up / down / left / right) human beings into zombies every hour. Find out how many hours does it take to infect all humans?

So subtasks can be defined as:

- find zombies
- infect neighbours adjacent to zombies
- repeat until all are zombies

You must separate finding zombies and infecting neighbours otherwise you will get incorrect result (how to separate existed zombies and newly created zombies).

Finding zombies is relatively easy. As we need to infect neighbours we should use indices to identify the location. For achieving that we can 'iterate over enumerated rows and for every enumerated item in row we return row-item number pair if item value is 1'

zombies = ((i, j) for i, row in enumerate(m) for j, item in enumerate(row) if item == 1)
Now we have locations (row, col) of zombies.

How to find neighbours?

If we have coordinate of zombie, then to get previous (to the left of zombie) we should change coordinates (0, -1), to get next (to the right of zombie) we shold change (0, 1), for row above (-1, 0) and row below (1, 0).

So we calculate coordinates of infected cells and change their values. What we should take into consideration: we shouldn't allow negative values (it will start counting from end); we will get IndexError for values in first and last row and column. Both of these are easily mitigated.

If we have 'infected' neighbours we should check whether humans are still present and if so repeat.
Meanwhile I found this to get inside the matrix and scroll through it
list_zombies_human =[[0,1,1,0,1],[0,1,0,1,0],[0,0,0,0,1],[0,1,0,0,0]]

for mat , arr in enumerate(list_zombies_human):
  for row_1, row in enumerate(arr):     
        print(row)
        for e in row:
            if e == 0:
              e = 1
            print(e)
but I have error in the last loop
Error:
TypeError: 'int' object is not iterable
I don't know how familiar you are with matrices, but:

>>> list_zombies_human =[[0,1,1,0,1],[0,1,0,1,0],[0,0,0,0,1],[0,1,0,0,0]]                  
>>> list_zombies_human[1][1]        # item in second row in second position (0-based index)                                                             
1
>>> list_zombies_human[1][2] = 1    # turn right neighbour into zombie; (0, 1) change in coordinates                                                           
>>> list_zombies_human                                                                     
[[0, 1, 1, 0, 1], [0, 1, 1, 1, 0], [0, 0, 0, 0, 1], [0, 1, 0, 0, 0]]
I don't have much experience with it but I'm learning now doing this exercise.
Why my approach isn't correct?
I tried also to replace with this:
[1 if x == 0 else x for x in range(len(row))]
but I had the same error.
Pages: 1 2