Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Playing pool with Pi

dave1707dave1707 Mod
in Code Sharing Posts: 7,599

I saw this topic on another forum and thought I’d try it with Codea. The subject is calculating the value of Pi by counting the number of collisions using 2 balls and a wall. What this program shows is a red ball moving towards a blue ball. I count the number of collisions that the blue ball has with the wall and the red ball. That count gives the value of Pi. Using M1 mass of 100 and M2 mass of 1, I can only get Pi to 1 decimal position. To get 2 positions, M1 has to be 1,000. 3 positions, M1 has to be 10,000, etc. The Codea Physics engine doesn’t work right if I use M1 mass with 1,000 or higher. That’s just too much of a mass difference between the 2 balls. This example for 1 digit is sufficient to show how this works. For more info, do a Google search on “Playing pool with Pi”.

displayMode(FULLSCREEN)

function setup()
    physics.continuous=true
    cnt=0
    pi=0
    nbr=2

    b1=physics.body(CIRCLE,20)
    b1.x=WIDTH
    b1.y=140
    b1.linearVelocity=vec2(-200,0)
    b1.friction=0
    b1.restitution=1
    b1.info="ball"
    b1.mass=10^nbr

    b2=physics.body(CIRCLE,20)
    b2.x=250
    b2.y=140  
    b2.friction=0
    b2.restitution=1
    b2.mass=1

    e1=physics.body(EDGE,vec2(0,120),vec2(WIDTH,120)) 
    e2=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) 
    e2.info="edge"
end

function draw()
    background(40, 40, 50)    
    noStroke()
    fill(255,0,0)
    ellipse(b1.x,b1.y,40)
    fill(0,0,255)
    ellipse(b2.x,b2.y,40)
    fill(255)

    strokeWidth(2)
    stroke(255)
    line(0,120,WIDTH,120)
    line(0,0,0,HEIGHT)
    text("Calculate pi using physics collisions.",WIDTH/2,HEIGHT-100)
    text('Do a Google search for "Playing pool with pi".',WIDTH/2,HEIGHT-140)
    text("Count = number of blue ball collisions with the wall or red ball.",WIDTH/2,HEIGHT-200)
    text("M1 = mass of red ball     100",WIDTH/2,HEIGHT-250)
    text("M2 = mass of blue ball    1",WIDTH/2,HEIGHT-280)
    text("Count = "..cnt,WIDTH/2,HEIGHT-350)
    text("pi = Count/sqrt(M1)",WIDTH/2,HEIGHT-390)
    text("pi = "..pi,WIDTH/2,HEIGHT-420)
end

function collide(c)
    if c.state==BEGAN then
        if c.bodyA.info=="edge" or c.bodyA.info=="ball" then
            cnt=cnt+1
            pi=cnt/10
        end
    end
end

Comments

  • SimeonSimeon Admin Mod
    Posts: 4,956

    Hah I just watched a video on this. So cool to see that it actually works in code.

    Though I notice if I increase the order of magnitude to 3 it does not simulate correctly

  • dave1707dave1707 Mod
    edited January 18 Posts: 7,599

    @Simeon I guess the Codea Physics engine can’t handle a mass that high (1,000) with collisions. The speed of the blue ball is just to great.

  • SimeonSimeon Admin Mod
    Posts: 4,956

    Yeah I think it breaks it :)

    This is like the most inefficient way to compute Pi, but really fun that it works

  • dave1707dave1707 Mod
    edited January 19 Posts: 7,599

    @Simeon Here’s a mathematical version of the graphics. This code was originally written in TiBasic by redsmith in another forum that I visit. I tried the original code on my TI 84 Plus SE and it worked, but was extreamly slow even for a few digits. I rewrote the code to run on the iPad. Use the slider to select the number of digits then press calc. It takes about 20 seconds to calculate 8 digits on my iPad Air. Each additional digit results in an increase of 10x. So 9 digits will take around 200 seconds.

    function setup()
        s=require("socket")
        parameter.integer("digits",1,14,1,function() C=0 en,st=0,0 end)
        parameter.action("calc",calc)
        calc()
    end
    
    function draw()
        background(0)
        text("Pi "..C/(10^(digits-1)),WIDTH/2,HEIGHT/2)
        text("Calc time  "..en-st,WIDTH/2,HEIGHT/2-100)
    end
    
    function calc()
        en,st=0,0
        output.clear()
        print("start")
        Z,C=0,0
        M1=1
        M2=100^(digits-1)
        V1,V2=0,-1
        cnt=0
        st=s.gettime()
        repeat
            cnt=cnt+1
            U=V1
            Y=V2       
            V1=(M1-M2)/(M1+M2)*U+2*M2/(M1+M2)*Y
            V2=2*M1/(M1+M2)*U+(M2-M1)/(M1+M2)*Y        
            if (V2-V1)<0 or V1<0 then
                C=C+1
            else
                Z=1
            end        
            V1=V1*-1        
            if (V2-V1)<0 or V1<0 then
                C=C+1
            else
                C=C+1
                Z=1
            end   
        until Z==1
        print("done")
        en=s.gettime()
    end
    
Sign In or Register to comment.