-1

I have an 8x8 grid of different numbers, and I want to get the elements of the diagonal that contains a given starting position. Here is an example

l = [[str(randint(1,9)) for i in range(8)] for n in range(8)]

>> [
[1 5 2 8 6 9 6 8]
[2 2 2 2 8 2 2 1]
[9 5 9 6 8 2 7 2]
[2 8 8 6 4 1 8 1]
[2 5 5 5 4 4 7 9]
[3 9 8 8 9 4 1 1]
[8 9 2 4 2 8 4 3]
[4 4 7 8 7 5 3 6]
]

How would I go about getting the left diagonal from the position x=4 and y=3 (so 4th list and 5th element in that list)? So The diagonal I would want would be [8,2,2,4,5,8,9,4].

I essentially asked this question yesterday, and a user was able to help me with getting the right diagonal with this code:

def rdiagonal(m, x, y):
   #x
   row = max((y - x, 0))
   #y
   col = max((x - y, 0))
   while row < len(m) and col < len(m[row]):
       yield m[row][col]
       row += 1
       col += 1

I tried to change that code to get the left diagonal also, but could not figure it out. What changes would I need to make to get the left diagonal?

Altaaf Ackbar
  • 99
  • 1
  • 9

3 Answers3

1

First of all, note that in the right diagonal, i=j, so you don't need two variables for row and col, as they'll always be equal along the main diagonal.

For the left one, notice that in this case j=l-i, where l=length(arr) is the length of your rows. Thus the following code will do:

def leftdiagonal(arr):
    k =[]
    dim = len(arr)-1
    for i in range(dim+1):
            k.append(arr[i][dim-i])
    return(k)
  • I'm sorry if it wasn't clear in my question, but I am looking for a way to find the left diagonal given a point on the array. That's what the row and col variables took into account. I wasn't just looking for the main left diagonal, I am looking for any diagonal given a point on the array. How could I achieve this? – Altaaf Ackbar Feb 27 '19 at 21:39
  • @AltaafAckbar see my answer below. It works in general. – Tim Feb 27 '19 at 22:39
0

If you think about it like a graph on 2D plane. Row is the y and column is the x. However, python definition of row index increases downward, so 'y' is flipped. This means the origin is on upper left corner and 'y' increases as it goes down.

This means 2 things:

  1. You can flip the rows of your list and you can use the function you already have
  2. Or you can build a new function without touching the list. Logic is below.

'y' being flipped means the diagonal you want is essentially the following function

y = c - x

And finding c would allow you to find the diagonal. Naturally,

c = x + y

So to find the rightmost col or col with largest index,

rightmost_row = min(len(m)-1, c)

To find the lowest row, observe

x = c - y

So

lowest_row = c - rightmost_row 

Then, you can navigate from top right to bottom left. Your current code moves from top left corner toward bottom right.


The code below gets you left diagonal.

def ldiagonal(m, x, y):
    #c
    c = x + y
    #x
    col = min((c, len(m)-1))
    #y
    row = c - col
    while col >= 0 and row < len(m[row]):
        yield m[row][col]
        col -= 1
        row += 1

Hope these can get you started.

Tim
  • 3,178
  • 1
  • 13
  • 26
0

To start from any point:

def ldiagonal(m, x, y):
  while y >= 0 and x < len(m):
     yield m[x][y]
     x += 1
     y -= 1

print(list(ldiagonal(m, 0, 0))) #=> [1]
print(list(ldiagonal(m, 0, 7))) #=> [8, 2, 2, 4, 5, 8, 9, 4] # it's the main
print(list(ldiagonal(m, 4, 4))) #=> [4, 8, 2, 4]
print(list(ldiagonal(m, 7, 7))) #=> [6]
iGian
  • 11,023
  • 3
  • 21
  • 36