2nd Graded Sheet: 🎯


Task 1.

Let's continue with our Dart-throwing example, that we solved in the last exercise. Now we sort of move towards the Generic programming.

Here are some solutions from the last exercise, so we have the following score function,

function score(x, y; outer = 10, middle = 5, inner = 1)
    z = (x^2 + y^2)

    if 0 < inner < middle < outer 

        if z  inner
            return 10
        elseif z  middle
            return 5
        elseif z  outer
            return 1
        else
            return 0
        end

    else
        begin
        throw(ArgumentError("argument must be nonnegative 
        and follow inner < middle < outer"))
        end
    end
    
end

Then using the following code you could generate one data point from Uniform([10,10])Uniform([-10, 10]) (this only generate one data point! in particular randpoint_uniform(10) won't work, but this is fine for us now!)

randpoint_uniform()  = 20*rand() - 10

Which in theory means, if we have XUniform([0,1])X \sim Uniform([0, 1]), then if we scale it by 20 and then also shift it by 10-10, this gives us a new random variable YY, where YUniform([10,10])Y \sim Uniform([-10, 10]). So in this case Y=20X10Y = 20X - 10. Bottomline, we can generate random points between the interval -10 to 10 which are equally likely to be appeared, we call this function randpoint_uniform().

Question 3 of the last exercise asked to you to generate points specifically from this distribution. Let's say you can generate 100 random points, and then calculate scores for each of these hundred points, store all the points in a vector and then store all the scores in a vector. Plot the points on the dart picture and then plot the scores as a histogram, and that's it. I apologize because the question was not so clear. Here is the function which will do the job for you

function scores_of_all_throws(number_of_throws)

    all_points = zeros(2, number_of_throws) ## pre-allocate a zero vector

    for i = 1:number_of_throws
        ## we are looping over the columns
        all_points[:, i] .= randpoint_uniform(), randpoint_uniform()  ## why not array?? [  ]
    end

    scores = score.(all_points[1, :], all_points[2, :]) ## broadcast, generate two points
    
    return scores, all_points

end

Because the function returns two objects we can also save the return in two objects

scores, points = scores_of_all_throws(1000)

You can also check with @btime from BenchmarkTools package to see the performance (time + allocation) and then also check with @code_warntype to check the type-stability.

Ok now we come to task,

a). Generic Programming with functions

Define a generic function scores_of_all_throws(dist, number_of_throws) where dist is going to be either randpoint_uniform() or randn() where randn() function will generate the a data point from a standard Normal distribution.

Now use the function scores_of_all_throws(dist, number_of_throws) to generate the data for 1000 throws. And save the returns in two vectors, one for all scores and one for all points. Plot the points in a histogram.

b). Generic Programming with types

Now we take the problem to a more Generic extension, so we will define our own custom types,

dtu = DartThrowerUniform(10,10)
d1 = DartboardThreeCircle(10,5,1) 

scores, points = scores_of_all_throws(dtu, 10, d1)

Now do the plotting, plot the scores for 1000 throws in a histogram. Here are the specifications for the single variate distributions (of course when you draw it is going to be bivariate but since iid, knowing single variate is enough!)