25
\$\begingroup\$

Happy Pi Day everyone! For no reason at all, I'm trying to construct a Monte Carlo estimator of Pi that is as short as possible. Can we construct one that can fit in a tweet?

To clarify, what I have in mind is the typical approach of drawing random points from the unit square and calculating the ratio that fall within the unit circle. The number of samples can be hard coded or not. If you hardcode them, you must use at least 1000 samples. The result may be returned or printed as a floating point, fixed point or rational number.

No trig functions or Pi constants, must be a Monte Carlo approach.

This is code golf, so the shortest submission (in bytes) wins.

\$\endgroup\$
  • 2
    \$\begingroup\$ are trig functions allowed? I suggest you explicitly ban them. \$\endgroup\$ – Level River St Mar 14 '15 at 16:08
  • \$\begingroup\$ ((0..4e9).map{rand**2+rand**2<1}.to_s.sub(/./,"$1.") \$\endgroup\$ – John Dvorak Mar 14 '15 at 18:37
  • \$\begingroup\$ @JanDvorak How is that supposed to work? Doesn't the map give you an array of true and false? \$\endgroup\$ – Martin Ender Mar 14 '15 at 19:16
  • \$\begingroup\$ @MartinBüttner Ah, oops, sorry. .filter{...}.size should work, though. \$\endgroup\$ – John Dvorak Mar 14 '15 at 19:51
  • \$\begingroup\$ @JanDvorak Indeed. That's really neat :) \$\endgroup\$ – Martin Ender Mar 14 '15 at 19:53

35 Answers 35

1
\$\begingroup\$

MathGolf, 11 bytes

0♫ô4ƒ²)/+♫/

Try it online!

Explanation

0            Push 0 (used for the sum)
 ♫           Push 10000
  ô          Start block of length 6
   4         Push 4
    ƒ²       Push random float in range [0,1) and square
      )      Increment by 1
       /     Divide
        +    Add result to the total sum (last instruction of block)
         ♫/  Divide by 10000

I'll add an explanation tomorrow. It performs 10000 iterations using the same integral as many other languages.

Assuming number of iterations as input:

MathGolf, 10 bytes

ô4ƒ²)/+\/(

Try it online!

Explanation

ô           Start block of length 6
 4          Push 4
  ƒ²        Push random float in range [0,1) and square
    )       Increment by 1
     /      Divide
      +     Add result to the total sum (last instruction of block)
            The first iteration, this adds the result to the implicit input, meaning that if the input is 10000 and the result is 3.1, 10003.1 is pushed on the stack. The end result is 10000 too large.
       \    Swap the top two elements on the stack (pushes the implicit input to the top)
        /   Divide (Since the sum is wonky, this is around 4.14159...)
         (  Decrement by one, resulting in 3.14159...)
\$\endgroup\$
1
\$\begingroup\$

APL(NARS), 79 chars, 158 bytes

r←q;f;i
   f←{1e8÷⍨?1e8}⋄i←r←0
A: i←i+1⋄r←r+1>(f*2)+f*2⋄→A×⍳i<1e5
   r←4×r÷1e5

%pi=3.1415926535897932385... test:

  q 
3.14284
  q
3.14256
  q
3.13832
\$\endgroup\$
0
\$\begingroup\$

Go, 130 116 bytes

import."math/rand";func p(){r,c,i:=Float64,0,1e6;for;i>0;i--{a,b:=r(),r();if a*a+b*b<1{c+=4}};print(float64(c)/1e6)}

No real tricks here, other than aliasing rand.Float64 and float64 to save a few bytes.

Run it here: http://play.golang.org/p/F5YniIncor

Please note that random on play.golang.org cannot be seeded by time (since the date is always the same) so you need to change the seed manually.

1e6 is used since the run time is too long for play.golang.org if I set it higher.

Edit: No longer takes an input, outputs the computed value itself.

\$\endgroup\$
0
\$\begingroup\$

Pyt, 22 bytes

Đ0⇹`⇹ṛ²ṛ²+1≤+⇹⁻łŕ⇹ᵮ/4*

Try it online!

Explanation:

          Implicit input [the number of random points to be sampled]
Đ         Duplicate input
0         Push zero
⇹         Swap the top two items on the stack
`...(ł)   Do ... (while the top of the stack is not 0)
⇹         Swap the top two items on the stack
ṛ²ṛ²+     Add the squares of two random floats (between 0 and 1)
1≤        Is the sum less than or equal to 1?
+         Add the top two items on the stack [auto-converts boolean to int]
⇹         Swap the top two items on the stack
⁻         Decrement the top of the stack by 1
(`)...ł   (Do ...) while the top of the stack is not 0
ŕ         Remove the top of the stack
⇹         Swap the top two items on the stack
ᵮ         Cast the top of the stack to a float
/         Divide
4*        Multiply by 4
          Implicit output
\$\endgroup\$
0
\$\begingroup\$

Python 3, 69 bytes

Apparently shorter than the other python entries, save one that uses sympy numpy (misremembered)

from random import*
print(eval(('+(1>('+2*'+random()**2)')*2000)/500)

Try it online!

Wow, it's been a while since I posted a multiline answer on this site... I've been using Turtlèd too much for that

Explanation:

from random import*    We can use random.random now as random
print(                 Print the result of the following
      eval(            evaluate the value of the expression in the string
           ('+(1>('+2*'+random()**2)')*2000    the string construction
                                           )/500) divide by 500 and print

Explanation of the string expression:

                             *2000  repeat this 2000 times
    '+(1>('                         have each section joined by a +,
                                    and the first item have the unary +. (nop, essentially)
                                    check if the section is less than 1, if so,
                                    evaluate to 1, else 0
           +2*'+random()**2)'        sum two random numbers squared, close both parens.

                                   [Evaluate the sum]

This is about the max accuracy, because 3000 samples gives a recursion error.

(I'll improve this explanation real soon actually.)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.