F#, 149 bytes
open System;
let r=new Random()
let q()=
let b=r.NextDouble()
b*b
let m(s:float)=(s-Seq.sumBy(fun x->q()+q()|>Math.Sqrt|>Math.Floor)[1.0..s])*4.0/s
Try it online!
As far as I can make out, to do this kind of running total in F# it's shorter to create an array of numbers and use the Seq.sumBy
method than use a for..to..do
block.
What this code does it that it creates a collection of floating-point numbers from 1 to s
, performs the function fun x->...
for the number of elements in the collection, and sums the result. There are s
elements in the collection, so the random test is done s
times. The actual numbers in the collection are ignored (fun x->
, but x
is not used).
It also means that the application has to first create and fill the array, and then iterate over it. So it's probably twice as slow as a for..to..do
loop. And with the array creation memory usage is in the region of O(f**k)!
For the actual test itself, instead of using an if then else
statement what it does is it calculates the distance (q()+q()|>Math.Sqrt
) and rounds it down with Math.Floor
. If the distance is within the circle, it'll be rounded down to 0. If the distance is outside the circle it'll be rounded down to 1. The Seq.sumBy
method will then total these results.
Note then that what Seq.sumBy
has totalled is not the points inside the circle, but the points outside it. So for the result it takes s
(our sample size) and subtracts the total from it.
It also appears that taking a sample size as a parameter is shorter than hard-coding the value. So I am cheating a little bit...