I’m wondering if there’s an efficient way to return all of the elements in a matrix that are diagonal to some starting point. For example, given the following matrix:
julia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
4×4 Array{Int64,2}:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
If I want to query the matrix to return all elements that are diagonal to the number 7 (so A[2,3]
), I should get back [2, 12, 4, 10, 13]
. If I query the matrix at point A[4,4]
(where 16 is), I would want to get back [1,6,11]
.
Is there a package that already does something like this or is this going to take a custom function?
EDIT: The matrices that I need this for will always be square
How about Diagonal(A)
? You will need to put using LinearAlgebra
first to bring in the package. In general, you might want to read Linear Algebra · The Julia Language
Hi Oscar. So it looks like this simply converts my matrix into a Diagonal
matrix, keeping only the main diagonal. Am I missing something here? Can I use this to get all elements that are diagonal and anti-diagonal to some specific point?
I think you are definitely going to need to write your own function for that.
1 Like
I think you are definitely going to need to write your own function for that.
This won’t be happening at this hour on a Sunday night I’ll take a crack at it tomorrow and if I come up with something decent I’ll post here
Oh, sorry, I misread your question.
Does this work? It’s not optimized, but should be decent
function diagonals(A::Matrix{T},i,j) where T
s = size(A)
out = Vector{T}()
for row in 1:s[1]
if i == row
continue
end
col1 = j - (i-row)
if 1 <= col1 <= s[2]
append!(out, A[row,col1])
end
col2 = j + (i-row)
if 1 <= col2 <= s[2]
append!(out, A[row,col2])
end
end
return out
end
2 Likes
Might make sense to exploit the strideness:
julia> function diagonals(A, i, j)
n = size(A,1)
s = (j-1)*n + i
[A[s-(n+1):-(n+1):begin]; A[s+(n+1):(n+1):end]; A[s+(n-1):(n-1):end-1]; A[s-(n-1):-(n-1):begin+1]]
end
diagonals (generic function with 1 method)
julia> diagonals(A, 2,3)
5-element Array{Int64,1}:
2
12
4
10
13
Though the code still needs to be fixed for edge cases:
julia> diagonals(A,4,4) # this is wrong
7-element Array{Int64,1}:
11
6
1
4
7
10
13
2 Likes
Alright, here’s what I came up with. It performs horrendously compared to either of the solutions posted by @Oscar_Smith and @dlfivefifty and it deviates a bit from the stated objective as it returns two different vectors, both of which include the element at the query starting point. About the only thing that it has going for it is that it’s a one-liner:
diagonals(A, i, j) = diag(A,j-i), diag(reverse(A,dims=1),(i+j)-(size(A,1)+1))
julia> A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
4×4 Array{Int64,2}:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
julia> diagonals(A,3,4)
([2, 7, 12], [15, 12])
julia> diagonals(A,2,2)
([1, 6, 11, 16], [9, 6, 3])
1 Like