How to put even numbers from matrix in separate vector in Julia? - matrix

I am solving some matrix problems in Julia and i need to put numbers that can be divided by 2 (or any other number) from matrix in separate vector. Generally, when I need to separate numbers from matrix that can be divided with 2 or 3 or 4...etc i can't index them properly. Basically, I need Julia equivalent for Matlab command:
vector=matrix(rem(matrix,2)==0)
.
I tried few things mentioned below:
vector=matrix[matrix.%2==0];
vector=(matrix.%2==0);
I expect output to be vector of numbers that can be divided with certain number but in first case I get errors and in second I only get "true" or "false".
This is my first post, so sorry if I made any mistakes or broke any rules.
Thanks in advance!

First of all, welcome to stackoverflow!
One way to get what you want, that you almost got right, is the following:
julia> M = rand(1:10, 3,3)
3×3 Array{Int64,2}:
3 10 7
6 7 8
2 10 6
julia> v = M[M .% 2 .== 0]
6-element Array{Int64,1}:
6
2
10
10
8
6
Note the extra dot in .== which applies the equality comparison elementwise.
A faster version would be to use findall:
julia> M[findall(x->x%2==0, M)]
6-element Array{Int64,1}:
6
2
10
10
8
6
Here, x->x%2==0 is a anonymous function representing the find criterium. In the special case x%2==0 this can simply be replaced by iseven:
julia> M[findall(iseven, M)]
6-element Array{Int64,1}:
6
2
10
10
8
6
You can also utilize array-comprehensions to get what you want as well, which should be even faster:
julia> [x for x in M if iseven(x)]
6-element Array{Int64,1}:
6
2
10
10
8
6
Finally, perhaps the most idomatic option, is to use filter:
julia> filter(iseven, M)
6-element Array{Int64,1}:
6
2
10
10
8
6

Related

Can you check for duplicates by taking the sum of the array and then the product of the array?

Let's say we have an array of size N with values from 1 to N inside it. We want to check if this array has any duplicates. My friend suggested two ways that I showed him were wrong:
Take the sum of the array and check it against the sum 1+2+3+...+N. I gave the example 1,1,4,4 which proves that this way is wrong since 1+1+4+4 = 1+2+3+4 despite there being duplicates in the array.
Next he suggested the same thing but with multiplication. i.e. check if the product of the elements in the array is equal to N!, but again this fails with an array like 2,2,3,2, where 2x2x3x2 = 1x2x3x4.
Finally, he suggested doing both checks, and if one of them fails, then there is a duplicate in the array. I can't help but feel that this is still incorrect, but I can't prove it to him by giving him an example of an array with duplicates that passes both checks. I understand that the burden of proof lies with him, not me, but I can't help but want to find an example where this doesn't work.
P.S. I understand there are many more efficient ways to solve such a problem, but we are trying to discuss this particular approach.
Is there a way to prove that doing both checks doesn't necessarily mean there are no duplicates?
Here's a counterexample: 1,3,3,3,4,6,7,8,10,10
Found by looking for a pair of composite numbers with factorizations that change the sum & count by the same amount.
I.e., 9 -> 3, 3 reduces the sum by 3 and increases the count by 1, and 10 -> 2, 5 does the same. So by converting 2,5 to 10 and 9 to 3,3, I leave both the sum and count unchanged. Also of course the product, since I'm replacing numbers with their factors & vice versa.
Here's a much longer one.
24 -> 2*3*4 increases the count by 2 and decreases the sum by 15
2*11 -> 22 decreases the count by 1 and increases the sum by 9
2*8 -> 16 decreases the count by 1 and increases the sum by 6.
We have a second 2 available because of the factorization of 24.
This gives us:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
Has the same sum, product, and count of elements as
1,3,3,4,4,5,6,7,9,10,12,13,14,15,16,16,17,18,19,20,21,22,22,23
In general you can find these by finding all factorizations of composite numbers, seeing how they change the sum & count (as above), and choosing changes in both directions (composite <-> factors) that cancel out.
I've just wrote a simple not very effective brute-force function. And it shows that there is for example
1 2 4 4 4 5 7 9 9
sequence that has the same sum and product as
1 2 3 4 5 6 7 8 9
For n = 10 there are more such sequences:
1 2 3 4 6 6 6 7 10 10
1 2 4 4 4 5 7 9 9 10
1 3 3 3 4 6 7 8 10 10
1 3 3 4 4 4 7 9 10 10
2 2 2 3 4 6 7 9 10 10
My write-only c++ code is here: https://ideone.com/2oRCbh

How to get product of all elements in a row of matrix in Julia

I'm using Julia and trying to get a vector p. The elements of p is the multiplying product of all elements in the same row of matrix P. I can do it by using for loops on each row, but is there a more efficient way to do it?
Thanks :)
Sounds like you should be able to do
julia> P = reshape(1:9, 3, 3)
3×3 reshape(::UnitRange{Int64}, 3, 3) with eltype Int64:
1 4 7
2 5 8
3 6 9
julia> prod.(eachrow(P))
3-element Vector{Int64}:
28
80
162

Julialang: In-place sort for columns of a matrix

I have a huge matrix and want to sort the columns in place for speed/memory efficency. Is it possible to use in-place sort for the columns of a matrix in Julia?
As an example, take the following matrix:
julia> M=Matrix{Int}(3,3);
julia> for i = 1:size(M)[1]
for j = 1:size(M)[2]
M[i,j]=3*(j-1)+i
end
end
julia> M
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
I want to use in-place sort for the columns to obtain the matrix
3×3 Array{Int64,2}:
3 6 9
2 5 8
1 4 7
This can be obtained without in-place sort as follows:
julia> M_sorted=Matrix{Int}(3,3);
julia> for j = 1:size(M)[2]
M_sorted[:,j]=sort(M[:,j],rev=true)
end
julia> M_sorted
3×3 Array{Int64,2}:
3 6 9
2 5 8
1 4 7
But something like that fails (here only for one column):
julia> sort!(M[:,1],rev=true)
3-element Array{Int64,1}:
3
2
1
julia> M
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
Is there any way to use in-place sort in this case? Note that there is no problem with the indexing since the matrix is saved column-wise in memory:
julia> M[1:end]
9-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
So I think it should be possible.
Slicing creates a copy of the column and sorts on that. If you instead want to directly sort in the memory of the existing array, use a view. Example:
M=Matrix{Int}(undef,3,3)
for i = 1:size(M)[1]
for j = 1:size(M)[2]
M[i,j]=3*(j-1)+i
end
end
M
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
sort!(#view(M[:,1]),rev=true)
M
3×3 Array{Int64,2}:
3 4 7
2 5 8
1 6 9

How can I subtract columns from a 2D array of JULIA?

I'm new to julia and I have a problem.
I am working with Julia (Jupyter notebook) and I do not know how can I do column 3 - column 2 and write the result as a new column at the end of the matrix/array2D.
I have tried this:
newCol = array[(1:end),3] - array[(1:end),2]
Any suggestion?
You can subtract the two columns and then concatenate it with the original array using the normal build-an-array syntax:
julia> arr
2x3 Array{Int32,2}:
1 2 3
5 6 7
julia> [arr [arr[:,3] - arr[:,2]]]
2x4 Array{Int32,2}:
1 2 3 1
5 6 7 1
Or use hcat:
julia> hcat(arr,arr[:,3] - arr[:,2])
2x4 Array{Int32,2}:
1 2 3 1
5 6 7 1
(Note that neither of these act in place, so you'd need to assign the result somewhere if you want to use it later.)

matlab for loop: fastest and most efficient method to reproduce large matrix

My data is a 2096x252 matrix of double values. I need a for loop or an equivalent which performs the following:
Each time the matrix is reproduced the first array is deleted and the second becomes the first. When the loop runs again, the remaining matrix is reproduced and the first array is deleted and the next becomes the first and so on.
I've tried using repmat but it is too slow and tedious when dealing with large matrices (2096x252).
Example input:
1 2 3 4
3 4 5 6
3 5 7 5
9 6 3 2
Desired output:
1 2 3 4
3 4 5 6
3 5 7 5
9 6 3 2
3 4 5 6
3 5 7 5
9 6 3 2
3 5 7 5
9 6 3 2
9 6 3 2
Generally with Matlab it is much faster to pre-allocate a large array than to build it incrementally. When you know in advance the final size of the large array there's no reason not to follow this general advice.
Something like the following should do what you want. Suppose you have an array in(nrows, ncols); then
indices = [0 nrows:-1:1];
out = zeros(sum(indices),ncols);
for ix = 1:nrows
out(1+sum(indices(1:ix)):sum(indices(1:ix+1)),:) = in(ix:end,:);
end
This worked on your small test input. I expect you can figure out what is going on.
Whether it is the fastest of all possible approaches I don't know, but I expect it to be much faster than building a large matrix incrementally.
Disclaimer:
You'll probably have memory issues with large matrices, but that is not the question.
Now, to the business:
For a given matrix A, the straightforward approach with the for loop would be:
[N, M] = size(A);
B = zeros(sum(1:N), M);
offset = 1;
for i = 1:N
B(offset:offset + N - i, :) = A(i:end, :);
offset = offset + size(A(i:end, :), 1);
end
B is the desired output matrix.
However, this solution is expected to be slow as well, because of the for loop.
Edit: preallocated B instead of dynamically changing size (this optimization should achieve a slight speedup).

Resources