Awesome
100 Julia Exercises with Solutions
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;
Question 001
Import the LinearAlgebra
package under the name LA
. (★☆☆)
import LinearAlgebra as LA;
Question 002
Print the version of Julia. (★☆☆)
println(VERSION);
1.8.2
Question 003
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
Question 004
Find the memory size of any array. (★☆☆)
sizeof(vA)
80
Question 005
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, ...)
.
Examples
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.
Question 006
Create a vector of zeros of size 10 but the fifth value which is 1. (★☆☆)
vA = zeros(10);
vA[5] = 1.0;
vA
10-element Vector{Float64}:
0.0
0.0
0.0
0.0
1.0
0.0
0.0
0.0
0.0
0.0
Question 007
Create a vector with values ranging from 7 to 12. (★☆☆)
vA = 7:12
7: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
Question 008
Reverse a vector (first element becomes last). (★☆☆)
vA = collect(1:3);
vB = vA[end:-1:1];
vB
3-element Vector{Int64}:
3
2
1
Alternative 001:
vB = reverse(vA);
Alternative 002 (In place):
reverse!(vA);
vA
3-element Vector{Int64}:
3
2
1
Question 009
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;
Question 010
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
Question 011
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
Question 012
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
Question 013
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);
Question 014
Create a random vector of size 30 and find the mean value. (★☆☆)
meanVal = mean(randn(30))
-0.04218053798839749
Question 015
Create a 2d array with 1 on the border and 0 inside. (★☆☆)
mA = zeros(4, 4);
mA[:, [1, end]] .= 1;
mA[[1, end], :] .= 1;
mA
4×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];
Question 016
Add a border of zeros around the array. (★☆☆)
mB = zeros(size(mA) .+ 2);
mB[2:(end - 1), 2:(end - 1)] = mA;
mB
7×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
Question 017
Evaluate the following expressions. (★☆☆)
0 * NaN
NaN
NaN == NaN
false
Inf > NaN
false
NaN - NaN
NaN
NaN in [NaN]
false
0.3 == 3 * 0.1
false
Question 018
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
Question 019
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;
mA
8×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];
Question 020
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
Question 021
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
Question 022
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
Question 023
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)
Question 024
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
Question 025
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;
Question 026
Sum the array 1:4
with initial value of -10. (★☆☆)
sum(1:4, init = -10)
0
Question 027
Consider an integer vector vZ
validate the following expressions. (★☆☆)
vZ .^ vZ
2 << vZ >> 2
vZ <- vZ
1im * vZ
vZ / 1 / 1
vZ < Z > Z
vZ = rand(1:10, 3);
vZ .^ vZ
3-element Vector{Int64}:
387420489
387420489
46656
try
2 << vZ >> 2
catch e
println(e)
end
MethodError(<<, (2, [9, 9, 6]), 0x0000000000007f1f)
vZ <- vZ
false
1im * vZ
3-element Vector{Complex{Int64}}:
0 + 9im
0 + 9im
0 + 6im
vZ / 1 / 1
3-element Vector{Float64}:
9.0
9.0
6.0
vZ < vZ > vZ
false
Question 028
Evaluate the following expressions. (★☆☆)
[0] ./ [0]
1-element Vector{Float64}:
NaN
try
[0] .÷ [0]
catch e
println(e)
end
DivideError()
try
convert(Float, convert(Int, NaN))
catch e
println(e)
end
InexactError(:Int64, Int64, NaN)
Question 029
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
Question 030
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
Question 031
Suppress Julia's warnings. (★☆☆)
One could use Suppressor.jl.
Question 032
Compare sqrt(-1)
and sqrt(-1 + 0im)
. (★☆☆)
try
sqrt(-1)
catch e
println(e)
end
DomainError(-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
Question 033
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
Question 034
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
Question 035
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));
Question 036
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.5
3×3 Matrix{Float64}:
0.0 0.0 4.0
2.0 3.0 4.0
-0.0 3.0 3.0
Option 3:
mA .÷ 1
3×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
Question 037
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);
Question 038
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];
Question 039
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
Question 040
Create a random vector of size 10 and sort it. (★★☆)
vA = rand(1:10, 10);
sort(vA) #<! Use `sort!()` for inplace sorting
10-element Vector{Int64}:
1
3
3
4
4
4
7
8
9
10
Question 041
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
Question 042
Check for equality of 2 arrays. (★★☆)
vA = rand(10);
vB = rand(10);
all(vA .== vB)
false
Question 043
Make an array immutable (Read only). (★★☆)
This is a work in progress for Julia at in Issue 31630.
Question 044
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)';
Question 045
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;
vA
10-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 `.=`
Question 046
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 mX
5×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 mY
5×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)')`
Question 047
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
Question 048
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));
end
0
255
0
65535
0
4294967295
0
18446744073709551615
-128
127
-32768
32767
-2147483648
2147483647
-9223372036854775808
9223372036854775807
-Inf
Inf
-Inf
Inf
-Inf
Inf
Question 049
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]
Question 050
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
Question 051
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];
Question 052
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 norm
5×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
Question 053
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
vB
Question 054
Read 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
Question 055
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);
end
1
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
Question 056
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';
Question 057
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);
Question 058
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
Question 059
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]);
Question 060
Tell if a given 2D array has null (All zeros) columns. (★★☆)
mA = rand(0:1, 3, 9);
any(all(iszero.(mA), dims = 1))
false
Question 061
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
Question 062
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
Question 063
Create an array class that has a name attribute. (★★☆)
One could use NamedArrays.jl
or AxisArrays.jl
.
Question 064
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]
Question 065
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
.
Question 066
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
Question 067
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
Question 068
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]
Question 069
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
Question 070
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]
Question 071
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 Julia
5×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
Question 072
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]
Question 073
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]
Question 074
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
end
Question 075
Compute 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;
end
Another 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-8
true
Question 076
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
end
Question 077
Negate a boolean or to change the sign of a float inplace. (★★★)
vA = rand(Bool, 10);
vA .= .!vA;
vA = randn(10);
vA .*= -1;
Question 078
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
Question 079
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
Question 080
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;
end
Question 081
Consider 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]
Question 082
Compute a matrix rank. (★★★)
numRows = 5;
numCols = 4;
mA = randn(numRows, numCols);
rank(mA)
4
Question 083
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);
end
Question 084
Extract 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]
Question 085
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;
mA
2×2 Main.var"##312".SymmetricMatrix{Int64}:
0 5
5 0
Question 086
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 == vB
true
Question 087
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
vB
16-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
Question 088
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.
Question 089
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
Question 090
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)
Question 091
Create an array which can be accessed like a record array in NumPy. (★★★)
One could use StructArrays.jl
.
Question 092
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;
end
vB ≈ vC ≈ vD
true
Question 093
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 == vE
true
Question 094
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
Question 095
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
mB
10×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);
Question 096
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 == vI
true
Question 097
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 product
true
Outer Product
@tullio mTullio[ii, jj] := vA[ii] * vB[jj]; #<! Outer product
mTullio ≈ vA * vB'
true
Sum
@tullio tullioVal = vA[ii];
tullioVal ≈ sum(vA) #<! Sum
true
Multiplication
@tullio vTullio[ii] := vA[ii] * vB[ii];
vTullio ≈ vA .* vB #<! Multiplication
true
Question 098
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.
Question 099
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)];
Question 100
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.