A set of introductory exercises for Julia. Based on 100 NumPy Exercises.
In order to generate this file:
- Clone the repository (Or download).
- Activate and instantiate the project.
- Run:
using Literate;
Literate.markdown("Julia100Exercises.jl", name = "README", execute = true, flavor = Literate.CommonMarkFlavor());Remark: Tested with Julia 1.8.2.
To Do:
- Reevaluate the difficulty level of each question.
using Literate;
using LinearAlgebra;
using Statistics;
using Dates;
using DelimitedFiles;
using UnicodePlots;
using Random;
using Tullio;
using StaticKernels;Import the LinearAlgebra package under the name LA. (★☆☆)
import LinearAlgebra as LA;Print the version of Julia. (★☆☆)
println(VERSION);1.8.2
Create a non initialized vector of size 10 of Float64. (★☆☆)
vA = Vector{Float64}(undef, 10)10-element Vector{Float64}:
0.0
1.314224183e-315
1.314224183e-315
0.0
1.314248214e-315
1.31427351e-315
0.0
1.314248214e-315
1.314106556e-315
0.0
Which is equivalent of
vA = Array{Float64, 1}(undef, 10)10-element Vector{Float64}:
0.0
1.314248214e-315
1.314106556e-315
0.0
1.314248214e-315
1.314106556e-315
0.0
1.314248214e-315
1.314106556e-315
0.0
Find the memory size of any array. (★☆☆)
sizeof(vA)80
Show the documentation of the + (Add) method. (★☆☆)
@doc ++(x, y...)
Addition operator. x+y+z+... calls this function with all arguments, i.e. +(x, y, z, ...).
julia> 1 + 20 + 4
25
julia> +(1, 20, 4)
25
dt::Date + t::Time -> DateTime
The addition of a Date with a Time produces a DateTime. The hour, minute, second, and millisecond parts of the Time are used along with the year, month, and day of the Date to create the new DateTime. Non-zero microseconds or nanoseconds in the Time type will result in an InexactError being thrown.
Create a vector of zeros of size 10 but the fifth value which is 1. (★☆☆)
vA = zeros(10);
vA[5] = 1.0;
vA10-element Vector{Float64}:
0.0
0.0
0.0
0.0
1.0
0.0
0.0
0.0
0.0
0.0
Create a vector with values ranging from 7 to 12. (★☆☆)
vA = 7:127:12
The above is efficient type. In order to explicitly create a vector:
vA = collect(7:12)6-element Vector{Int64}:
7
8
9
10
11
12
Reverse a vector (first element becomes last). (★☆☆)
vA = collect(1:3);
vB = vA[end:-1:1];
vB3-element Vector{Int64}:
3
2
1
Alternative 001:
vB = reverse(vA);Alternative 002 (In place):
reverse!(vA);
vA3-element Vector{Int64}:
3
2
1
Create a 3x3 matrix with values ranging from 0 to 8. (★☆☆)
mA = reshape(0:8, 3, 3)3×3 reshape(::UnitRange{Int64}, 3, 3) with eltype Int64:
0 3 6
1 4 7
2 5 8
Another way would be:
mA = Matrix{Float64}(undef, 3, 3);
mA[:] = 0:8;Find indices of non zero elements from [1, 2, 0, 0, 4, 0]. (★☆☆)
findall(!iszero, [1, 2, 0, 0, 4, 0])3-element Vector{Int64}:
1
2
5
Create a 3x3 identity matrix. (★☆☆)
mA = I(3)3×3 LinearAlgebra.Diagonal{Bool, Vector{Bool}}:
1 ⋅ ⋅
⋅ 1 ⋅
⋅ ⋅ 1
An alternative method (Explicit matrix) would be:
mA = Matrix(I, 3, 3) #<! For Float64: Matrix{Float64}(I, 3, 3)3×3 Matrix{Bool}:
1 0 0
0 1 0
0 0 1
Create a 2x2x2 array with random values. (★☆☆)
mA = randn(2, 2, 2)2×2×2 Array{Float64, 3}:
[:, :, 1] =
-1.34961 -0.225955
0.116267 1.03802
[:, :, 2] =
0.737672 2.2642
-0.839961 0.218133
Create a 5x5 array with random values and find the minimum and maximum values. (★☆☆)
mA = rand(5, 5);
minVal = minimum(mA)0.02305480092860468
maxVal = maximum(mA)0.9708814560256962
Using extrema() one could get both values at once:
minVal, maxVal = extrema(mA);Create a random vector of size 30 and find the mean value. (★☆☆)
meanVal = mean(randn(30))-0.04218053798839749
Create a 2d array with 1 on the border and 0 inside. (★☆☆)
mA = zeros(4, 4);
mA[:, [1, end]] .= 1;
mA[[1, end], :] .= 1;
mA4×4 Matrix{Float64}:
1.0 1.0 1.0 1.0
1.0 0.0 0.0 1.0
1.0 0.0 0.0 1.0
1.0 1.0 1.0 1.0
An alternative way (Different dimensions):
mA = ones(4, 5);
mA[2:(end - 1), 2:(end - 1)] .= 0;Using one line code:
mA = zeros(4, 5);
mA[[LinearIndices(mA)[cartIdx] for cartIdx in CartesianIndices(mA) if (any(cartIdx.I .== 1) || cartIdx.I[1] == size(mA, 1) || cartIdx.I[2] == size(mA, 2))]] .= 1;By Tomer Arnon:
numRows = 5;
numCols = 4;
mA = Int[ii ∈ (1, numRows) || jj ∈ (1, numCols) for ii in 1:numRows, jj in 1:numCols];Add a border of zeros around the array. (★☆☆)
mB = zeros(size(mA) .+ 2);
mB[2:(end - 1), 2:(end - 1)] = mA;
mB7×6 Matrix{Float64}:
0.0 0.0 0.0 0.0 0.0 0.0
0.0 1.0 1.0 1.0 1.0 0.0
0.0 1.0 0.0 0.0 1.0 0.0
0.0 1.0 0.0 0.0 1.0 0.0
0.0 1.0 0.0 0.0 1.0 0.0
0.0 1.0 1.0 1.0 1.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0
Evaluate the following expressions. (★☆☆)
0 * NaNNaN
NaN == NaNfalse
Inf > NaNfalse
NaN - NaNNaN
NaN in [NaN]false
0.3 == 3 * 0.1false
Create a 5x5 matrix with values [1, 2, 3, 4] just below the diagonal. (★☆☆)
mA = diagm(5, 5, -1 => 1:4)5×5 Matrix{Int64}:
0 0 0 0 0
1 0 0 0 0
0 2 0 0 0
0 0 3 0 0
0 0 0 4 0
Create a 8x8 matrix and fill it with a checkerboard pattern. (★☆☆)
mA = zeros(8, 8);
mA[2:2:end, 1:2:end] .= 1;
mA[1:2:end, 2:2:end] .= 1;
mA8×8 Matrix{Float64}:
0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0
1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0
0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0
1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0
0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0
1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0
0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0
1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0
By Tomer Arnon (https://github.com/tomerarnon):
mA = Int[isodd(ii + jj) for ii in 1:8, jj in 1:8];Convert the linear index 100 to a Cartesian Index of a size (6,7,8). (★☆☆)
mA = rand(6, 7, 8);
cartIdx = CartesianIndices(mA)[100]; #<! See https://discourse.julialang.org/t/14666
mA[cartIdx] == mA[100]true
Create a checkerboard 8x8 matrix using the repeat() function. (★☆☆)
mA = repeat([0 1; 1 0], 4, 4)8×8 Matrix{Int64}:
0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0
Normalize a 4x4 random matrix. (★☆☆)
mA = rand(4, 4);
mA .= (mA .- mean(mA)) ./ std(mA) #<! Pay attention that `@.` will yield error (`std()` and `mean()`)4×4 Matrix{Float64}:
-1.0589 0.696722 0.474169 0.0807478
1.33922 1.23329 -0.559528 -1.24305
-0.652489 0.919517 1.16875 -1.49035
-0.0565761 0.0550669 0.711533 -1.61812
Create a custom type that describes a color as four unsigned bytes (RGBA). (★☆☆)
struct sColor
R::UInt8;
G::UInt8;
B::UInt8;
A::UInt8;
end
sMyColor = sColor(rand(UInt8, 4)...)Main.var"##312".sColor(0xb0, 0xae, 0x35, 0x81)
Multiply a 2x4 matrix by a 4x3 matrix. (★☆☆)
mA = rand(2, 4) * randn(4, 3)2×3 Matrix{Float64}:
-1.47402 -1.10919 -1.22996
-0.745242 0.188422 -3.19746
Given a 1D array, negate all elements which are between 3 and 8, in place. (★☆☆)
vA = rand(1:10, 8);
map!(x -> ((x > 3) && (x < 8)) ? -x : x, vA, vA)8-element Vector{Int64}:
-6
3
1
-4
3
-4
-5
-4
Julia allows Math like notation as well (See Q0027):
vA = rand(1:10, 8);
map!(x -> 3 < x < 8 ? -x : x, vA, vA)8-element Vector{Int64}:
-7
-6
-4
1
-6
10
8
-5
Using logical indices one could use:
vA[3 .< vA .< 8] .*= -1;Sum the array 1:4 with initial value of -10. (★☆☆)
sum(1:4, init = -10)0
Consider an integer vector vZ validate the following expressions. (★☆☆)
vZ .^ vZ
2 << vZ >> 2
vZ <- vZ
1im * vZ
vZ / 1 / 1
vZ < Z > ZvZ = rand(1:10, 3);vZ .^ vZ3-element Vector{Int64}:
387420489
387420489
46656
try
2 << vZ >> 2
catch e
println(e)
endMethodError(<<, (2, [9, 9, 6]), 0x0000000000007f1f)
vZ <- vZfalse
1im * vZ3-element Vector{Complex{Int64}}:
0 + 9im
0 + 9im
0 + 6im
vZ / 1 / 13-element Vector{Float64}:
9.0
9.0
6.0
vZ < vZ > vZfalse
Evaluate the following expressions. (★☆☆)
[0] ./ [0]1-element Vector{Float64}:
NaN
try
[0] .÷ [0]
catch e
println(e)
endDivideError()
try
convert(Float, convert(Int, NaN))
catch e
println(e)
endInexactError(:Int64, Int64, NaN)
Round away from zero a float array. (★☆☆)
vA = randn(10);
map(x -> x > 0 ? ceil(x) : floor(x), vA)10-element Vector{Float64}:
1.0
-1.0
-1.0
-1.0
2.0
-1.0
2.0
2.0
2.0
1.0
Find common values between two arrays. (★☆☆)
vA = rand(1:10, 6);
vB = rand(1:10, 6);
vA[findall(in(vB), vA)]2-element Vector{Int64}:
7
5
Suppress Julia's warnings. (★☆☆)
One could use Suppressor.jl.
Compare sqrt(-1) and sqrt(-1 + 0im). (★☆☆)
try
sqrt(-1)
catch e
println(e)
endDomainError(-1.0, "sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).")
sqrt(-1 + 0im)0.0 + 1.0im
Display yesterday, today and tomorrow's date. (★☆☆)
println("Yesterday: $(today() - Day(1))");
println("Today: $(today())");
println("Tomorrow: $(today() + Day(1))");Yesterday: 2022-10-26
Today: 2022-10-27
Tomorrow: 2022-10-28
Display all the dates corresponding to the month of July 2016. (★★☆)
collect(Date(2016,7,1):Day(1):Date(2016,7,31))31-element Vector{Dates.Date}:
2016-07-01
2016-07-02
2016-07-03
2016-07-04
2016-07-05
2016-07-06
2016-07-07
2016-07-08
2016-07-09
2016-07-10
2016-07-11
2016-07-12
2016-07-13
2016-07-14
2016-07-15
2016-07-16
2016-07-17
2016-07-18
2016-07-19
2016-07-20
2016-07-21
2016-07-22
2016-07-23
2016-07-24
2016-07-25
2016-07-26
2016-07-27
2016-07-28
2016-07-29
2016-07-30
2016-07-31
Compute ((mA + mB) * (-mA / 2)) in place. (★★☆)
mA = rand(2, 2);
mB = rand(2, 2);
mA .= ((mA .+ mB) .* (.-mA ./ 2))2×2 Matrix{Float64}:
-0.35038 -0.685683
-0.510546 -0.444504
Using the dot macro:
@. mA = ((mA + mB) * (-mA / 2));Extract the integer part of a random array of positive numbers using 4 different methods. (★★☆)
mA = 5 * rand(3, 3);Option 1:
floor.(mA)3×3 Matrix{Float64}:
0.0 0.0 4.0
2.0 3.0 4.0
0.0 3.0 3.0
Option 2:
round.(mA .- 0.5) #<! Generates -0.0 for numbers smaller than 0.53×3 Matrix{Float64}:
0.0 0.0 4.0
2.0 3.0 4.0
-0.0 3.0 3.0
Option 3:
mA .÷ 13×3 Matrix{Float64}:
0.0 0.0 4.0
2.0 3.0 4.0
0.0 3.0 3.0
Option 4:
mA .- rem.(mA, 1)3×3 Matrix{Float64}:
0.0 0.0 4.0
2.0 3.0 4.0
0.0 3.0 3.0
Create a 5x5 matrix with row values ranging from 0 to 4. (★★☆)
mA = repeat(reshape(0:4, 1, 5), 5, 1)5×5 Matrix{Int64}:
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
One could also generate row like range using tranpose:
mA = repeat((0:4)', 5, 1);Generate an array using a generator of 10 numbers. (★☆☆)
vA = collect(x for x in 1:10)10-element Vector{Int64}:
1
2
3
4
5
6
7
8
9
10
In Julia the result of collect can be achieved directly using Array Comprehension:
vA = [x for x in 1:10];Create a vector of size 10 with values ranging from 0 to 1, both excluded. (★★☆)
vA = LinRange(0, 1, 12)[2:(end - 1)]10-element LinRange{Float64, Int64}:
0.0909091,0.181818,0.272727,0.363636,…,0.636364,0.727273,0.818182,0.909091
Create a random vector of size 10 and sort it. (★★☆)
vA = rand(1:10, 10);
sort(vA) #<! Use `sort!()` for inplace sorting10-element Vector{Int64}:
1
3
3
4
4
4
7
8
9
10
Implement the sum() function manually. (★★☆)
vA = rand(100);
function MySum(vA::Vector{T}) where{T <: Number}
sumVal = vA[1];
for ii in 2:length(vA)
sumVal += vA[ii];
end
return sumVal;
end
MySum(vA)51.34991384741698
Check for equality of 2 arrays. (★★☆)
vA = rand(10);
vB = rand(10);
all(vA .== vB)false
Make an array immutable (Read only). (★★☆)
This is a work in progress for Julia at in Issue 31630.
Consider a random 10x2 matrix representing cartesian coordinates, convert them to polar coordinates. (★★☆)
mA = rand(10, 2);
ConvToPolar = vX -> [hypot(vX[1], vX[2]), atan(vX[2], vX[1])]
mB = [ConvToPolar(vX) for vX in eachrow(mA)]10-element Vector{Vector{Float64}}:
[0.9505364569557584, 0.031648622825633764]
[0.704392126760974, 0.5147716023358581]
[0.29679995764188105, 1.201649642883764]
[0.637435149299262, 0.02987122275134911]
[0.933745980010277, 0.7244055260446777]
[0.9187482092583683, 0.36651502794834323]
[1.0164226188075605, 0.9581226557842126]
[0.5946171056720952, 1.4392243895565575]
[0.7889136757232136, 0.2964469880257975]
[1.044698619009772, 0.8754548962664869]
In order to have the same output size:
mC = reduce(hcat, mB)';Create random vector of size 10 and replace the maximum value by 0. (★★☆)
vA = randn(10);In case of a single maximum or all different values:
vA[argmax(vA)] = 0;
vA10-element Vector{Float64}:
0.15593661212531384
0.8177229521444311
-1.4850097210409072
0.0
0.8552383451908633
1.476127811761641
0.2407698166125247
-0.6363509339561092
-0.5514594178114751
0.8756142494364301
General solution:
maxVal = maximum(vA);
vA .= (valA == maxVal ? 0 : valA for valA in vA); #<! Non allocating generator by using `.=`Create a a grid of x and y coordinates covering the [0, 1] x [0, 1] area. (★★☆)
numGridPts = 5;
vX = LinRange(0, 1, numGridPts);
vY = LinRange(0, 1, numGridPts);
MeshGrid = (vX, vY) -> ([x for _ in vY, x in vX], [y for y in vY, _ in vX]);
mX, mY = MeshGrid(vX, vY); #<! See https://discourse.julialang.org/t/48679
@show mX5×5 Matrix{Float64}:
0.0 0.25 0.5 0.75 1.0
0.0 0.25 0.5 0.75 1.0
0.0 0.25 0.5 0.75 1.0
0.0 0.25 0.5 0.75 1.0
0.0 0.25 0.5 0.75 1.0
@show mY5×5 Matrix{Float64}:
0.0 0.0 0.0 0.0 0.0
0.25 0.25 0.25 0.25 0.25
0.5 0.5 0.5 0.5 0.5
0.75 0.75 0.75 0.75 0.75
1.0 1.0 1.0 1.0 1.0
By Tomer Arnon:
mXY = [(ii, jj) for ii in 0:0.25:1, jj in 0:0.25:1]; #<! Also `tuple.(0:0.25:1, (0:0.25:1)')`Given two vectors, vX and vY, construct the Cauchy matrix mC: (Cij = 1 / (xi - yj)). (★★☆)
vX = rand(5);
vY = rand(5);
mC = 1 ./ (vX .- vY')5×5 Matrix{Float64}:
21.646 3.23455 34.1025 3.79522 -3.10044
12.1532 2.89647 15.2886 3.33807 -3.49101
5.11271 2.18076 5.59545 2.422 -5.77562
27.6005 3.34229 51.6618 3.94442 -3.00751
2.36374 1.45768 2.46193 1.56164 18.4072
Print the minimum and maximum representable value for each Julia scalar type. (★★☆)
vT = [UInt8 UInt16 UInt32 UInt64 Int8 Int16 Int32 Int64 Float16 Float32 Float64]
for juliaType in vT
println(typemin(juliaType));
println(typemax(juliaType));
end0
255
0
65535
0
4294967295
0
18446744073709551615
-128
127
-32768
32767
-2147483648
2147483647
-9223372036854775808
9223372036854775807
-Inf
Inf
-Inf
Inf
-Inf
Inf
Print all the values of an array. (★★☆)
mA = rand(3, 3);
print(mA);[0.6807535316053605 0.849791747148149 0.32690265736495716; 0.9773227682466125 0.5276250185081583 0.9071015474523568; 0.3192975731085147 0.009594822627075117 0.21726819354916904]
Find the closest value to a given scalar in a vector. (★★☆)
inputVal = 0.5;
vA = rand(10);
vA[argmin(abs.(vA .- inputVal))]0.5023858297186229
By Tomer Arnon:
function ClosestValue(vA::Vector{T}, inputVal::T) where{T <: Number}
return argmin(y -> abs(y - inputVal), vA);
end
ClosestValue(vA, inputVal)0.5023858297186229
Create a structured array representing a position (x, y) and a color (r, g, b). (★★☆)
struct sPosColor
x::Int
y::Int
R::UInt8;
G::UInt8;
B::UInt8;
A::UInt8;
end
numPixels = 10;
maxVal = typemax(UInt32);
vMyColor = [sPosColor(rand(1:maxVal, 2)..., rand(UInt8, 4)...) for _ in 1:numPixels];Consider a random vector with shape (5, 2) representing coordinates, find the distances matrix mD: $ {D}{i, j} = {\left| {x}{i} - {x}{j} \right|}{2} $. (★★☆)
mX = rand(5, 2);
vSumSqr = sum(vX -> vX .^ 2, mX, dims = 2);
mD = vSumSqr .+ vSumSqr' - 2 * (mX * mX');
mD #<! Apply `sqrt.()` for the actual norm5×5 Matrix{Float64}:
-4.44089e-16 0.135171 0.729876 0.724544 0.525945
0.135171 0.0 0.539868 0.255352 0.136451
0.729876 0.539868 -1.38778e-17 0.403845 0.814356
0.724544 0.255352 0.403845 0.0 0.135001
0.525945 0.136451 0.814356 0.135001 -4.44089e-16
Convert a float (32 bits) array into an integer (32 bits) in place. (★★☆)
vA = 9999 .* rand(Float32, 5);
vB = reinterpret(Int32, vA); #<! Creates a view
@. vB = trunc(Int32, vA) #<! Updates the byes in th view (Inplace for `vA`)5-element reinterpret(Int32, ::Vector{Float32}):
8898
1815
6821
6523
9953
The above is equivalent of:
for ii in eachindex(vB)
vB[ii] = trunc(Int32, vA[ii]);
end
vBRead the following file (Q0054.txt). (★★☆)
1, 2, 3, 4, 5
6, , , 7, 8
, , 9,10,11
mA = readdlm("Q0054.txt", ',')3×5 Matrix{Any}:
1 2 3 4 5
6 " " " " 7 8
" " " " 9 10 11
Enumerate array in a loop. (★★☆)
mA = rand(3, 3);
for (elmIdx, elmVal) in enumerate(mA) #<! See https://discourse.julialang.org/t/48877
println(elmIdx);
println(elmVal);
end1
0.7028850425818378
2
0.9169645026836734
3
0.887675432103485
4
0.6988267487719038
5
0.7143993871851885
6
0.8303140449034555
7
0.43387559304673373
8
0.13163225199507878
9
0.6590727215475687
Generate a generic 2D Gaussian like array with μ = 0, σ = 1 and indices over {-5, -4, ..., 0, 1, ..., 5}. (★★☆)
vA = -5:5;
μ = 0;
σ = 1;
mG = [(1 / (2 * pi * σ)) * exp(-0.5 * ((([x, y] .- μ)' * ([x, y] .- μ)) / (σ * σ))) for x in vA, y in vA];
heatmap(mG) ┌───────────┐
11 │▄▄▄▄▄▄▄▄▄▄▄│ ┌──┐ 0.2
│▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
1 │▄▄▄▄▄▄▄▄▄▄▄│ └──┘ 2.0e-12
└───────────┘
1 11
Using the separability of the Gaussian function:
vG = (1 / (sqrt(2 * pi) * σ)) .* exp.(-0.5 .* (((vA .- μ) .^ 2) / (σ * σ)));
mG = vG * vG';Place 5 elements in a 5x5 array randomly. (★★☆)
mA = rand(5, 5);
mA[rand(1:25, 5)] = rand(5);Another option which avoids setting into the same indices:
mA[randperm(25)[1:5]] = rand(5);Subtract the mean of each row of a matrix. (★★☆)
mA = rand(3, 3);
mA .-= mean(mA, dims = 2);
mean(mA, dims = 1)1×3 Matrix{Float64}:
0.261517 -0.0218978 -0.23962
Sort an array by a column. (★★☆)
colIdx = 2;
mA = rand(3, 3);
mA[sortperm(mA[:, colIdx]), :]3×3 Matrix{Float64}:
0.870197 0.229455 0.462788
0.812345 0.61344 0.0990058
0.271644 0.722126 0.182457
Using sortslices():
sortslices(mA, dims = 1, by = x -> x[colIdx]);Tell if a given 2D array has null (All zeros) columns. (★★☆)
mA = rand(0:1, 3, 9);
any(all(iszero.(mA), dims = 1))false
Find the 2nd nearest value from a given value in an array. (★★☆)
inputVal = 0.5;
vA = rand(10);
vA[sortperm(abs.(vA .- inputVal))[2]]0.5947029703004421
Alternative way (More efficient)
closeFirst = Inf;
closeSecond = Inf;
closeFirstIdx = 0;
closeSecondIdx = 0;
# Using `global` for scope in Literate
for (elmIdx, elmVal) in enumerate(abs.(vA .- inputVal))
if (elmVal < closeFirst)
global closeSecond = closeFirst;
global closeFirst = elmVal;
global closeSecondIdx = closeFirstIdx;
global closeFirstIdx = elmIdx;
elseif (elmVal < closeSecond)
global closeSecond = elmVal;
global closeSecondIdx = elmIdx;
end
end
vA[closeSecondIdx] == vA[sortperm(abs.(vA .- inputVal))[2]]true
By Tomer Arnon:
vA[partialsortperm(abs.(vA .- inputVal), 2)]0.5947029703004421
Considering two arrays with shape (1, 3) and (3, 1), Compute their sum using an iterator. (★★☆)
vA = rand(1, 3);
vB = rand(3, 1);
sum(aVal + bVal for aVal in vA, bVal in vB)11.149909948305584
Create an array class that has a name attribute. (★★☆)
One could use NamedArrays.jl or AxisArrays.jl.
Given a vector, add 1 to each element indexed by a second vector (Be careful with repeated indices). (★★★)
vA = rand(1:10, 5);
vB = rand(1:5, 3);
println(vA);
# Julia is very efficient with loops
for bIdx in vB
vA[bIdx] += 1;
end
println(vA);[1, 6, 2, 6, 2]
[3, 7, 2, 6, 2]
Accumulate elements of a vector X to an array F based on an index list I. (★★★)
vX = rand(1:5, 10);
vI = rand(1:15, 10);
numElements = maximum(vI);
vF = zeros(numElements);
for (ii, iIdx) in enumerate(vI)
vF[iIdx] += vX[ii];
end
println("vX: $vX");
println("vI: $vI");
println("vF: $vF");vX: [5, 4, 3, 5, 2, 5, 2, 5, 5, 1]
vI: [3, 2, 6, 11, 12, 10, 5, 11, 12, 2]
vF: [0.0, 5.0, 5.0, 0.0, 2.0, 3.0, 0.0, 0.0, 0.0, 5.0, 10.0, 7.0]
One could also use counts() from StatsBase.jl.
Considering an image of size w x h x 3 image of type UInt8, compute the number of unique colors. (★★☆)
mI = rand(UInt8, 1000, 1000, 3);
numColors = length(unique([reinterpret(UInt32, [iPx[1], iPx[2], iPx[3], 0x00])[1] for iPx in eachrow(reshape(mI, :, 3))])); #<! Reshaping as at the moment `eachslice()` doesn't support multiple `dims`.
print("Number of Unique Colors: $numColors");Number of Unique Colors: 970711
Another option:
numColors = length(unique([UInt32(iPx[1]) + UInt32(iPx[2]) << 8 + UInt32(iPx[3]) << 16 for iPx in eachrow(reshape(mI, :, 3))]));
print("Number of Unique Colors: $numColors");Number of Unique Colors: 970711
Simpler way to slice a pixel:
numColors = length(unique([UInt32(mI[ii, jj, 1]) + UInt32(mI[ii, jj, 2]) << 8 + UInt32(mI[ii, jj, 3]) << 16 for ii in 1:size(mI, 1), jj in 1:size(mI, 2)]));
print("Number of Unique Colors: $numColors");Number of Unique Colors: 970711
Considering a four dimensions array, get sum over the last two axis at once. (★★★)
mA = rand(2, 2, 2, 2);
sum(reshape(mA, (2, 2, :)), dims = 3)2×2×1 Array{Float64, 3}:
[:, :, 1] =
1.817 1.16234
2.44291 2.32796
Considering a one dimensional vector vA, how to compute means of subsets of vA using a vector vS of same size describing subset indices. (★★★)
# Bascially extending `Q0065` with another vector of number of additions.
vX = rand(1:5, 10);
vI = rand(1:15, 10);
numElements = maximum(vI);
vF = zeros(numElements);
vN = zeros(Int, numElements);
for (ii, iIdx) in enumerate(vI)
vF[iIdx] += vX[ii];
vN[iIdx] += 1;
end
# We only divide the mean if the number of elements accumulated is bigger than 1
for ii in 1:numElements
vF[ii] = ifelse(vN[ii] > 1, vF[ii] / vN[ii], vF[ii]);
end
println("vX: $vX");
println("vI: $vI");
println("vF: $vF");vX: [5, 5, 4, 2, 1, 1, 3, 5, 3, 2]
vI: [14, 7, 8, 10, 5, 10, 14, 2, 7, 13]
vF: [0.0, 5.0, 0.0, 0.0, 1.0, 0.0, 4.0, 4.0, 0.0, 1.5, 0.0, 0.0, 2.0, 4.0]
Get the diagonal of a matrix product. (★★★)
mA = rand(5, 7);
mB = rand(7, 4);
numDiagElements = min(size(mA, 1), size(mB, 2));
vD = [dot(mA[ii, :], mB[:, ii]) for ii in 1:numDiagElements]4-element Vector{Float64}:
1.8937792321469207
1.035584608236753
2.0251852803210024
2.2065505485118653
Alternative way:
vD = reshape(sum(mA[1:numDiagElements, :]' .* mB[:, 1:numDiagElements], dims = 1), numDiagElements)4-element Vector{Float64}:
1.8937792321469207
1.035584608236753
2.0251852803210024
2.2065505485118653
Consider the vector [1, 2, 3, 4, 5], build a new vector with 3 consecutive zeros interleaved between each value. (★★★)
vA = 1:5;
# Since Julia is fast with loops, it would be the easiest choice
numElements = (4 * length(vA)) - 3;
vB = zeros(Int, numElements);
for (ii, bIdx) in enumerate(1:4:numElements)
vB[bIdx] = vA[ii];
end
println(vB);
# Alternative (MATLAB style) way:
mB = [reshape(collect(vA), 1, :); zeros(Int, 3, length(vA))];
vB = reshape(mB[1:(end - 3)], :);
println(vB);[1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5]
[1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5]
Consider an array of dimension 5 x 5 x 3, mulitply it by an array with dimensions 5 x 5 using broadcasting. (★★★)
mA = rand(5, 5, 3);
mB = rand(5, 5);
mA .* mB #<! Very easy in Julia5×5×3 Array{Float64, 3}:
[:, :, 1] =
0.492335 0.301617 0.0158155 0.411494 0.0331824
0.555254 0.148368 0.111992 0.366332 0.192798
0.104442 0.249306 0.0138448 0.018588 0.721434
0.665075 0.136419 0.00305929 0.430373 0.208216
0.290075 0.642668 0.519127 0.511527 0.151719
[:, :, 2] =
0.234647 0.447608 0.000903852 0.00299349 0.0626502
0.0159529 0.164814 0.0807125 0.27415 0.180858
0.103613 0.291711 0.00759939 0.013771 0.11713
0.314552 0.210101 0.00966737 0.343302 0.377711
0.129541 0.642804 0.833245 0.372239 0.816422
[:, :, 3] =
0.774094 0.181579 0.0151706 0.26963 0.0364216
0.167574 0.0016081 0.0130672 0.823491 0.398857
0.062678 0.40945 0.00790564 0.0141378 0.468662
0.344903 0.18419 0.00697708 0.487335 0.504131
0.118821 0.0130137 0.803091 0.754898 0.0470187
Swap two rows of a 2D array. (★★★)
mA = rand(UInt8, 3, 2);
println(mA);
mA[[1, 2], :] .= mA[[2, 1], :];
println(mA);UInt8[0xc7 0x2f; 0xbf 0x8f; 0xac 0x2a]
UInt8[0xbf 0x8f; 0xc7 0x2f; 0xac 0x2a]
Consider a set of 10 triplets describing 10 triangles (with shared vertices), find the set of unique line segments composing all the triangles. (★★★)
mA = rand(0:100, 10, 3); #<! Each row composes 3 veritces ([1] -> [2], [2] -> [3], [3] -> [1])
mC = [sort!([vC[mod1(ii, end)], vC[mod1(ii + 1, end)]]) for ii in 1:(size(mA, 2) + 1), vC in eachrow(mA)][:] #<! Sorted combinations of vertices
mC = unique(mC)30-element Vector{Vector{Int64}}:
[52, 86]
[23, 86]
[23, 52]
[53, 88]
[53, 95]
[88, 95]
[4, 31]
[4, 24]
[24, 31]
[34, 80]
[34, 99]
[80, 99]
[19, 69]
[19, 21]
[21, 69]
[38, 74]
[36, 74]
[36, 38]
[18, 20]
[20, 48]
[18, 48]
[0, 23]
[23, 77]
[0, 77]
[23, 42]
[42, 75]
[23, 75]
[20, 69]
[7, 69]
[7, 20]
Given a sorted array vC that corresponds to a bincount, produce an array vA such that bincount(vA) == vC. (★★★)
vC = rand(0:7, 5);
numElements = sum(vC);
vA = zeros(Int, numElements);
elmIdx = 1;
# Using `global` for scope in Literate
for (ii, binCount) in enumerate(vC)
for jj in 1:binCount
vA[elmIdx] = ii;
global elmIdx += 1;
end
endCompute averages using a sliding window over an array. (★★★)
numElements = 10;
winRadius = 1;
winReach = 2 * winRadius;
winLength = 1 + winReach;
vA = rand(0:3, numElements);
vB = zeros(numElements - (2 * winRadius));
aIdx = 1 + winRadius;
# Using `global` for scope in Literate
for ii in 1:length(vB)
vB[ii] = mean(vA[(aIdx - winRadius):(aIdx + winRadius)]); #<! Using integral / running sum it would be faster.
global aIdx += 1;
endAnother method using running sum:
vC = zeros(numElements - winReach);
jj = 1;
sumVal = sum(vA[1:winLength]);
vC[jj] = sumVal / winLength;
jj += 1;
# Using `global` for scope in Literate
for ii in 2:(numElements - winReach)
global sumVal += vA[ii + winReach] - vA[ii - 1];
vC[jj] = sumVal / winLength;
global jj += 1;
end
maximum(abs.(vC - vB)) < 1e-8true
Consider a one dimensional array vA, build a two dimensional array whose first row is [ vA[0], vA[1], vA[2] ] and each subsequent row is shifted by 1. (★★★)
vA = rand(10);
numCols = 3;
numRows = length(vA) - numCols + 1;
mA = zeros(numRows, numCols);
for ii in 1:numRows
mA[ii, :] = vA[ii:(ii + numCols - 1)]; #<! One could optimize the `-1` out
endNegate a boolean or to change the sign of a float inplace. (★★★)
vA = rand(Bool, 10);
vA .= .!vA;
vA = randn(10);
vA .*= -1;Consider 2 sets of points mP1, mP2 describing lines (2d) and a point vP, how to compute distance from the point vP to each line i: [mP1[i, :], mP2[i, :]. (★★★)
# See distance of a point from a line in Wikipedia (https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line).
# Specifically _Line Defined by Two Points_.
numLines = 10;
mP1 = randn(numLines, 2);
mP2 = randn(numLines, 2);
vP = randn(2);
vD = [(abs(((vP2[1] - vP1[1]) * (vP1[2] - vP[2])) - ((vP1[1] - vP[1]) * (vP2[2] - vP1[2]))) / hypot((vP2 - vP1)...)) for (vP1, vP2) in zip(eachrow(mP1), eachrow(mP2))];
minDist = minimum(vD);
println("Min Distance: $minDist");Min Distance: 0.42811311783896533
Consider 2 sets of points mP1, mP2 describing lines (2d) and a set of points mP, how to compute distance from the point vP = mP[j, :] to each line i: [mP1[i, :], mP2[i, :]. (★★★)
numLines = 5;
mP1 = randn(numLines, 2);
mP2 = randn(numLines, 2);
mP = randn(numLines, 2);
mD = [(abs(((vP2[1] - vP1[1]) * (vP1[2] - vP[2])) - ((vP1[1] - vP[1]) * (vP2[2] - vP1[2]))) / hypot((vP2 - vP1)...)) for (vP1, vP2) in zip(eachrow(mP1), eachrow(mP2)), vP in eachrow(mP)];
for jj in 1:numLines
minDist = minimum(mD[jj, :]);
println("The minimum distance from the $jj -th point: $minDist");
end┌ Warning: Assignment to `minDist` in soft scope is ambiguous because a global variable by the same name exists: `minDist` will be treated as a new local. Disambiguate by using `local minDist` to suppress this warning or `global minDist` to assign to the existing global variable.
└ @ string:9
The minimum distance from the 1 -th point: 0.33333028326949365
The minimum distance from the 2 -th point: 0.09596286876613971
The minimum distance from the 3 -th point: 0.15987404532559377
The minimum distance from the 4 -th point: 0.09922388894592074
The minimum distance from the 5 -th point: 0.0701461047753776
Consider an arbitrary 2D array, write a function that extract a subpart with a fixed shape and centered on a given element (Handel out of bounds). (★★★)
# One could use `PaddedViews.jl` to easily solve this.
arrayLength = 10;
winRadius = 3;
vWinCenter = [7, 9];
mA = rand(arrayLength, arrayLength);
winLength = (2 * winRadius) + 1;
mB = zeros(winLength, winLength);
verShift = -winRadius;
# Using `global` for scope in Literate
for ii in 1:winLength
horShift = -winRadius;
for jj in 1:winLength
mB[ii, jj] = mA[min(max(vWinCenter[1] + verShift, 1), arrayLength), min(max(vWinCenter[2] + horShift, 1), arrayLength)]; #<! Nearest neighbor extrapolation
horShift += 1;
end
global verShift += 1;
endConsider an array vA = [1, 2, 3, ..., 13, 14], generate an array vB = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], ..., [11, 12, 13, 14]]. (★★★)
vA = collect(1:14);
winNumElements = 4;
winReach = winNumElements - 1;
vB = [vA[ii:(ii + winReach)] for ii in 1:(length(vA) - winReach)]11-element Vector{Vector{Int64}}:
[1, 2, 3, 4]
[2, 3, 4, 5]
[3, 4, 5, 6]
[4, 5, 6, 7]
[5, 6, 7, 8]
[6, 7, 8, 9]
[7, 8, 9, 10]
[8, 9, 10, 11]
[9, 10, 11, 12]
[10, 11, 12, 13]
[11, 12, 13, 14]
Compute a matrix rank. (★★★)
numRows = 5;
numCols = 4;
mA = randn(numRows, numCols);
rank(mA)4
Find the most frequent value in an array. (★★★)
vA = rand(1:5, 15);MATLAB Style (Manual loop might be faster)
vB = unique(vA);
# vB[argmax(sum(vA .== vB', dims = 1)[:])] #<! The input to `argmax()` is a `1 x n` vector, hence squeezed so `argmax()` won't return Cartesian Index.
vB[argmax(dropdims(sum(vA .== vB', dims = 1), dims = 1))] #<! The input to `argmax()` is a `1 x n` vector, hence squeezed so `argmax()` won't return Cartesian Index.1
Comparing bits:
One could convert at the bits level to integers and then use something like counts() from StatsBase.jl.
Support to 1:4 bytes of data:
numBytes = sizeof(vA[1]);
if (sizeof(vA[1]) == 1)
vB = reinterpret(UInt8, vA);
elseif (sizeof(vA[1]) == 2)
vB = reinterpret(UInt16, vA);
elseif (sizeof(vA[1]) == 4)
vB = reinterpret(UInt32, vA);
elseif (sizeof(vA[1]) == 8)
vB = reinterpret(UInt64, vA);
endExtract all the contiguous 3x3 blocks from a random 5x5 matrix. (★★★)
numRows = 5;
numCols = 5;
mA = rand(1:9, numRows, numCols);
winRadius = 1;
winReach = 2 * winRadius;
winLength = winReach + 1;
mB = [mA[ii:(ii + winReach), jj:(jj + winReach)] for ii in 1:(numRows - winReach), jj in 1:(numCols - winReach)]3×3 Matrix{Matrix{Int64}}:
[9 1 1; 3 1 2; 9 4 6] [1 1 4; 1 2 2; 4 6 2] [1 4 7; 2 2 1; 6 2 2]
[3 1 2; 9 4 6; 4 2 1] [1 2 2; 4 6 2; 2 1 7] [2 2 1; 6 2 2; 1 7 1]
[9 4 6; 4 2 1; 2 9 8] [4 6 2; 2 1 7; 9 8 1] [6 2 2; 1 7 1; 8 1 4]
Create a 2D array struct such that mA[i, j] == mA[j, i] (Symmetric matrix). (★★★)
struct SymmetricMatrix{T <: Number} <: AbstractArray{T, 2}
numRows::Int
data::Matrix{T}
function SymmetricMatrix(mA::Matrix{T}) where {T <: Number}
size(mA, 1) == size(mA, 2) || throw(ArgumentError("Input matrix must be square"))
new{T}(size(mA, 1), Matrix(Symmetric(mA)));
end
end
function Base.size(mA::SymmetricMatrix)
(mA.numRows, mA.numRows);
end
function Base.getindex(mA::SymmetricMatrix, ii::Int)
mA.data[ii];
end
function Base.getindex(mA::SymmetricMatrix, ii::Int, jj::Int)
mA.data[ii, jj];
end
function Base.setindex!(mA::SymmetricMatrix, v, ii::Int, jj::Int)
setindex!(mA.data, v, ii, jj);
setindex!(mA.data, v, jj, ii);
end
mA = SymmetricMatrix(zeros(Int, 2, 2));
mA[1, 2] = 5;
mA2×2 Main.var"##312".SymmetricMatrix{Int64}:
0 5
5 0
Consider a set of p matrices of shape nxn and a set of p vectors with length n. Compute the sum of of the p matrix vector products at once (Result is a vector of length n). (★★★)
# One could use `TensorOperations.jl` or `Einsum.jl` for a more elegant solution.
numRows = 5;
numMat = 3;
tP = [randn(numRows, numRows) for _ in 1:numMat];
mP = [randn(numRows) for _ in 1:numMat];
vA = reduce(+, (mP * vP for (mP, vP) in zip(tP, mP)));vB = zeros(numRows);
for ii in 1:numMat
vB .+= tP[ii] * mP[ii];
end
vA == vBtrue
Consider a 16x16 array, calculate the block sum (Block size is 4x4). (★★★)
We solve a more general case for any size of blocks.
numRows = 16;
numCols = 8;
vBlockSize = [2, 4]; #<! [numRows, numCols] ./ vBlockSize == integer
mA = rand(numRows, numCols);
numBlocksVert = numRows ÷ vBlockSize[1];
numBlocksHori = numCols ÷ vBlockSize[2];
numBlocks = numBlocksVert * numBlocksHori;
mA = reshape(mA, vBlockSize[1], :);We number the blocks column wise and create their block index per column of the reshaped mA.
vBlockIdx = 1:numBlocks;
mBlockIdx = reshape(vBlockIdx, numBlocksVert, numBlocksHori);
mBlockIdx = repeat(mBlockIdx, 1, 1, vBlockSize[2]);
mBlockIdx = permutedims(mBlockIdx, (1, 3, 2));
vBlockIdx = mBlockIdx[:]; #<! Matches the block index per column of the reshaped `mA`.
vA = dropdims(sum(mA, dims = 1), dims = 1);
vB = zeros(numBlocks);
for ii = 1:(numBlocks * vBlockSize[2])
vB[vBlockIdx[ii]] += vA[ii];
end
vB16-element Vector{Float64}:
4.354231620225193
3.734856822720345
3.297606250613403
4.256409222766379
3.2941384563138993
3.776165923653995
3.600353929303568
4.518180088610547
3.6679777425586186
4.6420262282688345
4.296040312870272
5.1547123230902825
3.0214360614973477
3.202315920090961
4.669003591708878
3.3257368418156616
Implement the simulation Game of Life using arrays. (★★★)
numRows = 20;
numCols = 20;
gofKernel = @kernel w -> w[-1, -1] + w[-1, 0] + w[-1, 1] + w[0, -1] + w[0, 1] + w[1, -1] + w[1, 0] + w[1, 1];
gofNumLives = round(Int, 0.05 * numRows * numCols);
gofNumGenerations = 50;
vI = randperm(numRows * numCols)[1:gofNumLives];
mG = zeros(UInt8, numRows, numCols);
mG[vI] .= UInt8(1);
mB = similar(mG);
heatmap(mG) #<! Initialization ┌────────────────────┐
20 │▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ ┌──┐ 1
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
1 │▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ └──┘ 0
└────────────────────┘
1 20
for ii in 1:numGridPts
map!(gofKernel, mB, extend(mG, StaticKernels.ExtensionConstant(0))); #<! One may use `ExtensionCircular`
for ii in eachindex(mB)
mG[ii] = UInt8((mB[ii] >= 3) || ((mB[ii] > 0) && (mB[ii] == 2))); #<! Could be done with broadcasting
end
end
heatmap(mG) #<! Final state ┌────────────────────┐
20 │▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ ┌──┐ 1
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
│▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ │▄▄│
1 │▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄│ └──┘ 0
└────────────────────┘
1 20
TODO: Use O(1) implementation for Box Blur.
Get the n largest values of an array. (★★★)
vA = rand(10);
numValues = 3;
vA[partialsortperm(vA, 1:numValues, rev = true)]3-element Vector{Float64}:
0.8713271882275592
0.8486847944348448
0.8445471427655805
Given an arbitrary number of vectors, build the Cartesian Product (Every combinations of every item). (★★★)
function CartesianProduct(tupleX)
return collect(Iterators.product(tupleX...))[:];
end
vA = 1:3;
vB = 8:9;
vC = 4:5;
CartesianProduct((vA, vB, vC))12-element Vector{Tuple{Int64, Int64, Int64}}:
(1, 8, 4)
(2, 8, 4)
(3, 8, 4)
(1, 9, 4)
(2, 9, 4)
(3, 9, 4)
(1, 8, 5)
(2, 8, 5)
(3, 8, 5)
(1, 9, 5)
(2, 9, 5)
(3, 9, 5)
Create an array which can be accessed like a record array in NumPy. (★★★)
One could use StructArrays.jl.
Consider a large vector vA, compute vA to the power of 3 using 3 different methods. (★★★)
vA = rand(1000);Method 001:
vB = vA .^ 3;Method 002:
vC = [valA ^ 3 for valA in vA];Method 003:
vD = zeros(length(vA));
for (ii, valA) in enumerate(vA)
vD[ii] = valA * valA * valA;
endvB ≈ vC ≈ vDtrue
Consider two arrays mA and mB of shape 8x3 and 2x2. Find rows of mA that contain elements of each row of mB regardless of the order of the elements in mB. (★★★)
The way I interpret the question is rows in mA which contain at least 1 element from each row of mB.
mA = rand(0:4, 8, 3);
mB = rand(0:4, 2, 2);
mC = [any(vA .== vB') for vB in eachrow(mB), vA in eachrow(mA)]; #<! General solution, will work for any size of `mA` and `mB`
vD = [all(vC) for vC in eachcol(mC)]8-element Vector{Bool}:
0
1
1
1
0
0
1
1
In order to have a solution without the intermediate array mC
function Iterate2(iA; iterState = missing)
if(ismissing(iterState))
valA, iterState = iterate(iA);
else
valA, iterState = iterate(iA, iterState);
end
valB, iterState = iterate(iA, iterState);
return (valA, valB), iterState
end
tT = (any(vA .== vB') for vB in eachrow(mB), vA in eachrow(mA));
iterState = missing;
vE = zeros(Bool, size(mA, 1));
for ii = 1:length(vD)
global iterState;
(valA, valB), iterState = Iterate2(tT; iterState = iterState);
vE[ii] = valA && valB;
end
vD == vEtrue
Considering a 10x3 matrix, extract rows with unequal values. (★★★)
mA = rand(1:3, 10, 3);
vD = [maximum(vA) != minimum(vA) for vA in eachrow(mA)]10-element Vector{Bool}:
1
0
1
1
1
1
1
1
1
1
Convert a vector of ints into a matrix binary representation. (★★★)
vA = rand(UInt8, 10);
mB = zeros(Bool, length(vA), 8);
# See https://discourse.julialang.org/t/26663
for ii in 1:length(vA)
vS = bitstring(vA[ii]);
for jj in 1:size(mB, 2)
mB[ii, jj] = vS[jj] == '1';
end
end
mB10×8 Matrix{Bool}:
0 0 1 0 1 1 1 1
1 1 0 1 1 1 0 0
0 0 0 0 1 0 1 0
1 1 1 0 0 1 0 1
0 1 0 1 0 1 0 1
0 0 0 1 0 1 1 1
1 0 0 0 1 0 1 0
1 1 0 1 1 1 0 0
0 0 1 1 1 1 0 0
1 0 0 0 0 1 0 0
By Tomer Arnon:
mB = reverse!(reduce(hcat, digits.(vA, base = 2, pad = 8))', dims = 2);Given a two dimensional array, extract unique rows. (★★★)
mA = UInt8.(rand(1:3, 10, 3));
vS = [reduce(*, bitstring(valA) for valA in vA) for vA in eachrow(mA)]; #<! Supports any array!
vU = unique(vS);
vI = [findfirst(valU .== vS) for valU in vU];An alternative way:
vB = indexin(vU, vS);
vB == vItrue
Considering 2 vectors vA and vB, write the einsum equivalent (Using Einsum.jl) of inner, outer, sum, and mul function. (★★★)
vA = rand(5);
vB = rand(5);Inner Product
@tullio tullioVal = vA[ii] * vB[ii];
tullioVal ≈ dot(vA, vB) #<! Inner producttrue
Outer Product
@tullio mTullio[ii, jj] := vA[ii] * vB[jj]; #<! Outer product
mTullio ≈ vA * vB'true
Sum
@tullio tullioVal = vA[ii];
tullioVal ≈ sum(vA) #<! Sumtrue
Multiplication
@tullio vTullio[ii] := vA[ii] * vB[ii];
vTullio ≈ vA .* vB #<! Multiplicationtrue
Considering a path described by two vectors vX and vY, sample it using equidistant samples. (★★★)
The way I interpreted the question is to create sub segments of the same length.
numPts = 100;
numSegments = 1000;
vX = sort(10 * rand(numPts));
vY = sort(10 * rand(numPts));
vR = cumsum(hypot.(diff(vX), diff(vY)));
pushfirst!(vR, 0.0);
vRSegment = LinRange(0.0, vR[end], numSegments);
struct LinearInterpolator1D{T <: Number} <: AbstractArray{T, 1}
vX::Vector{T};
vY::Vector{T};
function LinearInterpolator1D(vX::Vector{T}, vY::Vector{T}) where {T <: Number}
length(vX) == length(vX) || throw(ArgumentError("Input vectors must have the same length"));
new{T}(vX, vY);
end
end
function Base.size(vA::LinearInterpolator1D)
size(vA.vX);
end
function Base.getindex(vA::LinearInterpolator1D, ii::Number)
if (ii >= vA.vX[end])
return vA.vY[end];
end
if (ii <= vA.vX[1])
return vA.vY[1];
end
rightIdx = findfirst(vA.vX .>= ii);
leftIdx = rightIdx - 1;
tt = (ii - vA.vX[leftIdx]) / (vA.vX[rightIdx] - vA.vX[leftIdx]);
return ((1 - tt) * vA.vY[leftIdx]) + (tt * vA.vY[rightIdx]);
end
function Base.setindex!(vA::LinearInterpolator1D, valX, valY, ii::Int, jj::Int)
setindex!(sLinInterp.vX, valX, ii);
setindex!(sLinInterp.vY, valY, ii);
end
vXInt = LinearInterpolator1D(vR, vX);
vYInt = LinearInterpolator1D(vR, vY);
vXSegment = [vXInt[intIdx] for intIdx in vRSegment];
vYSegment = [vYInt[intIdx] for intIdx in vRSegment];
hP = lineplot(vX, vY, canvas = DotCanvas, name = "Samples");
lineplot!(hP, vXSegment, vYSegment, name = "Interpolated");
hP ┌────────────────────────────────────────┐
10 │ ..:│ Samples
│ ...'' │ Interpolated
│ .:'' │
│ .: │
│ .: │
│ .:''' │
│ :' │
│ ..:' │
│ :'' │
│ ....: │
│ ..: │
│ :'''' │
│ .:'' │
│ .:' │
0 │..:' │
└────────────────────────────────────────┘
0 10
Remark: In order to be mathematically accurate the resolution of vRSegment must be high enough to be an integer factor of each segment.
It can be done if the resolution is 1 / (prod(vR)) which is easily infeasible with Float64. So this is a good enough approximation.
Given an integer n and a 2D array mA, find the rows which can be interpreted as draws from a multinomial distribution with n (Rows which only contain integers and which sum to n). (★★★)
mA = rand([0, 0.5, 1, 2, 3], 15, 3);
sumVal = 4;
vI = [all(vA .== round.(vA)) && sum(vA) == sumVal for vA in eachrow(mA)];Compute bootstrapped 95% confidence intervals for the mean of a 1D array vA. Namely, resample the elements of an array with replacement N times, compute the mean of each sample and then compute percentiles over the means. (★★★)
numTrials = 10000;
numSamples = 1000;
μ = 0.5;
vA = μ .+ randn(numSamples);
tM = (mean(vA[rand(1:numSamples, numSamples)]) for _ in 1:numTrials);
quantile(tM, [0.025, 0.975])2-element Vector{Float64}:
0.4620914889349693
0.5830619321705541
This page was generated using Literate.jl.