Python Forum
Matrix understanding in Python
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Matrix understanding in Python
#11
You task is not 'infect' all humans. Task is to infect humans who are next to zombies. But if you are changing values of 0 to 1 you don't check whether they are actually neighbours of zombies (both on rows and columns) or not.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#12
I thought that every human have to "infect" by zombies because the result is a matrix of all 1
 Input:
  [[0, 1, 1, 0, 1],
   [0, 1, 0, 1, 0],
   [0, 0, 0, 0, 1],
   [0, 1, 0, 0, 0]]
  Output: 2
  Why?
  At the end of the 1st hour, the status of the grid:
  [[1, 1, 1, 1, 1],
   [1, 1, 1, 1, 1],
   [0, 1, 0, 1, 1],
   [1, 1, 1, 0, 1]]

  At the end of the 2nd hour, the status of the grid:
  [[1, 1, 1, 1, 1],
   [1, 1, 1, 1, 1],
   [1, 1, 1, 1, 1],
   [1, 1, 1, 1, 1]]
Reply
#13
If you do 1 if x == 0 else x then after first 'hour' all 'humans' are turned into 'zombies'.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#14
I have no other solutions, it's a challenge too difficult for me
Reply
#15
Take a pencil and paper and try to visualise.

Matrix has rows and columns. Rows are lists inside lists and items in those lists are columns (keep in mind that Python uses zero indexing):

m = [[1, 2, 3],    # row with index 0 
     [4, 5, 6],    # row with index 1
     [7, 8, 9]]    # row with index 2
Columns are: [1, 4, 7] (index 0), [2, 5, 8] (index 1) and [3, 6, 9] (index 2).

So m[0][0] is 1 and m[1][1] is 5.

If we want to find neighbours up, down, left, right and have 'start coordinate' then:

- for up deduct one row
- for down add one row
- for left deduct one column
- for right add one column

So for position m[1][1] which is 5 we should perform following transactions:

- up, start [1][1], change [-1][0], [1-1, 1-0] -> [0][1] -> row zero column one -> 2
- down, start [1][1], change [1][0], [1+1][[1+0] -> [2][1] -> row two column one -> 8
- left, start [1][1], change [0, -1], [1+0][1-1] -> [1][0] -> row one column zero -> 4
- right, start [1][1], change [0, 1], [1+0][1+1] -> [1][2] -> row one column two -> 6

So far so good. However, we have corner cases:

[0][0] - if we deduct row or column we will get [-1] which is not IndexError in Python but index of last element. So while calculating neighbours coordinates we must ignore pairs where are negative values

[0][2] - if we add one column we will get [3] which is out of bounds (IndexError). We can use try...except to ignore IndexError and continue.

As I wrote earlier - one way to solve it is to find coordinates of zombies, based on that calculate coordinates of neighbours, then change neighbours values. Before next loop check whether there is any human left, if so repeat.

It's around 12 rows of code. If you can articulate your solution in spoken language translating into Python is not so difficult. If you don't have articulated plan it impossible. This is not about coding, its about problem solving.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#16
Don't give up quite yet. If you can understand this code, you are almost there:
import copy
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
matrix_copy = copy.deepcopy(matrix) # you need to make changes in a copy of the matrix based on the state of the first matrix
for row in range(len(matrix)) : # loop through the rows
    for col in range(len(matrix[0])) : #loop through the cols
        if matrix[row][col] == 1 : # if a cell is zombie, make neighbor cells zombies
            if row != 0 : # can't access row negative 1!
                matrix_copy[row-1][col] = 1
            if row != (len(matrix)-1) : # again checking for edge conditions
                matrix_copy[row+1][col] = 1
            if col != 0 :
                matrix_copy[row][col-1] = 1
            if col != (len(matrix[0])-1) :
                matrix_copy[row][col+1] = 1
                
print(matrix_copy) #This is your matrix after one time through
print(matrix) #original matrix unchanged
matrix = copy.deepcopy(matrix_copy) #copy so you can iterate
OK, a few things. The bunch of if statements check for border conditions. You want to change the cell above, below, left, and right but not left of a zero column cell or below the last cell on the matrix. If you just modify in the original matrix, then by modifying the cell to the right you will find another zombie cell and everything to the right gets changed. Same with down. So, must make modifications to a copy.

I used copy.deepcopy() because if I just use copy or "=" it copies the references and matrix and matrix_copy both end up pointing to the same cells. deepcopy() copies the objects in the lists.

To take this the rest of the way, you would need to write a quick loop through the matrix_copy that checks to see if there are any more zeros. Then (with proper indentation) put the whole thing except the initialization of the matrix into a while loop that exits when there are no more zeroes. The while loop needs to count the number of times it took to get to the all zombie state.

There are fancier ways to do this,tried to keep it simple.
Reply
#17
I don't think that following solution is 'fancier' than jefsummer's, it's just different possibility.

As this should be a learning process more throughout explanation than usually:

Pseudocode:

# define coordinates offsets
# define hours counter

# while there is human:
    # find all zombies coordinates
    # find all zombie neighbours coordinates with brute-force using coordinates offsets
    # for every zombie neighbour coordinate:
         # try set value to 1
         # except IndexError - continue
    # add one to hours
Following assumes that m is the matrix which consists initial state.

# define coordinates offsets
Relative changes in coordinates to find up/down/right/left:

offsets = [(0, -1), (0, 1), (1, 0), (-1, 0)]
# define hours counter
Set hours to zero

hours = 0
# while there is human
Find if there is 0 in matrix; for that we have to flatten matrix; I used set but list would do as well

while 0 in set(item for row in m for item in row):
# find all zombies coordinates
We need to find coordinates of items which value is 1: 'give me row and item index for every row and every item in row if item is equal to 1'. In order to get index I used enumerate:

zombies = ((i, j) for i, row in enumerate(m) for j, item in enumerate(row) if item == 1)
# find all zombie neighbours coordinates with brute-force using coordinates offsets
It's too complicated and brute force for my liking but it gets job done. 'give me row and item index adjusted with offset for every zombie coordinate if both row and item adjusted values are not less than zero' (negative values are not IndexErrors but start indexing from end and we don't want that; with Python 3.8 nice walrus should be done)

infected = [(i+row, j+col) for (i, j) in zombies for (row, col) in offsets if all([0 <= (i+row), 0 <=(j+col)])]
# for every zombie neighbour coordinate
Iterate through zombie neighbours coordinates.

for (row, column) in infected:
# try set value to 1
As coordinates contain out of bounds indices (last column and last row) then we try to change value

try:
    m[row][column] = 1
# except IndexError - continue
If we have zombies in last column/row and encounter IndexError - ignore and continue:

except IndexError:
    continue
# add one to hours
If changes are made add 1 hour

hours += 1
Everthing together:

offsets = [(0, -1), (0, 1), (1, 0), (-1, 0)]
hours = 0

while 0 in set(item for row in m for item in row):
    zombies = ((i, j) for i, row in enumerate(m) for j, item in enumerate(row) if item == 1)
    infected = [(i+row, j+col) for (i, j) in zombies for (row, col) in offsets if all([0 <= (i+row), 0 <=(j+col)])]
    for (row, column) in infected:
        try:
            m[row][column] = 1
        except IndexError:
            continue
    hours += 1
Of course, we can make 'infected' comprehension even more complicated and avoid try...except altogether (value check must be then 0 <= row indice < len(m); 0 <= col indice < len(m[0]))
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  define a diagonal matrix from a matrix amalalaoui 1 2,320 May-15-2019, 01:12 PM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020