Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Golf -- compute PI

by Ovid (Cardinal)
on Apr 16, 2002 at 00:18 UTC ( #159377=perlmeditation: print w/ replies, xml ) Need Help??

A friend was talking about computing PI, so wrote this script to compute it.

#!/usr/bin/perl -w #Compute pi. Based on Leibniz's algorithm that # pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11... use strict; my $pi = 4; my $next_digits = get_leibniz(); for ( 1 .. 100000 ) { my ( $subtract, $add ) = &$next_digits; $pi = $pi - $subtract + $add; } print $pi; sub get_leibniz { my $index = 1; my $sub = sub { $index += 2; my $first = 4/$index; $index += 2; my $second = 4/$index; return ($first, $second); }; return $sub; }

I can reduce that down to this:

$p=4;$n=l();for(1..100000){($s,$a)=&$n;$p=$p-$s+$a}print$p; sub l{$i=1;sub{$i+=2;$f=4/$i;$i+=2;$q=4/$i;($f,$q)}}

112 strokes. Admittedly, I'm rotten at golf. Any takers? No trig functions allowed :)

Update: I took four strokes off by eliminating a space and three superfluous semi-colons. Also, my answer is only correct to 5 digits. I could increase the second value in the for range, but that takes too long. Hadn't really thought about dealing with accuracy. Hmm...

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Comment on Golf -- compute PI
Select or Download Code
Re: Golf -- compute PI
by lhoward (Vicar) on Apr 16, 2002 at 01:39 UTC
    Here's my entry at 79 bytes. This is admittedly my first golf, so can probably stand some improvement.... It uses a probablistic method for determining pi. As tested below its usually accurate to 2 or 3 decimal places, but is sometimes worse. Accuracy can be increased by increasing the number of iterations.
    for(1..999999){$x=rand();$y=rand();$k++if sqrt($x*$x+$y*$y)<1}print 4* +$k/999999
    I managed to get it down to 61 bytes.... I'm still humbled by some of the other submissions....
    for(1..1e6){$k++if sqrt(rand()**2+rand()**2)<1}print $k*4/1e6
Re: Golf -- compute PI
by japhy (Canon) on Apr 16, 2002 at 01:42 UTC
    Here's code that comes in at 49 chars:
    $i=1;map$@+=4/($i+=4)-4/($i-2),0..99999;print$@+4

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a (from-home) job
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Golf -- compute PI
by jsprat (Curate) on Apr 16, 2002 at 01:55 UTC
    How about this (72 strokes - about par for the course ;-) for($i;$i<100000;$i+=2){$_.="+4/(($i*2)+1)-4/((($i+1)*2)+1)"};print eval

    I'm assuming the algorithm can't be changed.
    I just got rid of the neat closure and built it all in the loop. It's got the same five digits of accuracy. The same 72 strokes can have up to a whopping 6 digits of accuracy if you change the 100_000 to 999_999!

    jsprat

Re: Golf -- compute PI
by wog (Curate) on Apr 16, 2002 at 02:01 UTC
    $i+=1/(($_+=1e-7)**2+1)until$_>1;print$i/1e7*4 #23456789_123456789_123456789_123456789_123456 # 1 2 3 4

    46 chars. (Changes the algorithm.) Change all 7s to a higher number for a better approximation and slower runtime, change it to a lower number for worse approximation and faster runtime.

    update:

    $i+=($_&1?4:-4)/($_*2-1)for 1..1e6;print$i #23456789_123456789_123456789_123456789_12 # 1 2 3 4

    (another, similar solution was there breifly: 44 chars.Pretty much the same algorithm Ovid gave. (The 4 is just factored out.))

    42 chars. The same algorithm Ovid gave. (Change the 6 to a higher number for a better approximation, etc.)

      Shave another
      $i+=($_%2*8-4)/($_*2-1)for 1..1e6;print$i
      or equivalently
      $i+=4*(-1)**$_/(1-$_*2)for 1..1e6;print$i
Re: Golf -- compute PI (boo)
by boo_radley (Parson) on Apr 16, 2002 at 02:06 UTC
    An apparent 67.
    #000000001111111111222222222233333333334444444444555555555566666666 #234567890123456789012345678901234567890123456789012345678901234567 $i=43;$p=1;eval'$x'.chr($i).'=4/$p;$p+=2;$i^=6'for 1..10**5;print$x
    update :
    #0000000011111111112222222222333333333344444444445555555555 #2345678901234567890123456789012345678901234567890123456789 $o=1;$t=3;for(1..1e5){$e+=(4/$o)-(4/$t);$o+=4;$t+=4}print$e

    Simplify, simplify... :)
    update :
    to Chmrr : (1**5) yeah, I saw that in another solution and felt rather sheepish. As to the exact value of the number, I felt it appropriate to use something approximate to Ovid's original algorithm.

      1e5 is shorter than 10**5. This applies equally to all of the solutions given so far. However, as this number only defines the accuracy of the answer, it is arguable that the length of this number should not be counted towards the total par for the answer..

      perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

        Another "short than 10**5" option is to use a..eqxe instead.

        _____________________________________________________
        Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a (from-home) job
        s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Golf -- compute PI
by metadoktor (Hermit) on Apr 16, 2002 at 02:53 UTC
    Hmmm....25 char pi with accuracy up to 15 digits...does this count? Just kidding. Ha ha ;)

    sub pi { # 1 2 #1234567890123456789012345 print"3.14159265358979\n"; }

    Actually, I think it is a little tricky to devise a Perl program that accurately calculates pi. A monk once made this post that seemed to inaccurately calculate pi.

    metadoktor

    "The doktor is in."

Re: Golf -- compute PI
by belg4mit (Prior) on Apr 16, 2002 at 03:42 UTC
    Yes, ignoring accuracy I could win with $p=22/7; or in some states $p=3; :-D Oh come on, somebody had to say it.

    --
    perl -pe "s/\b;([mnst])/'\1/mg"

Re: Golf -- compute PI
by andreychek (Parson) on Apr 16, 2002 at 04:05 UTC
    Here's a few more methods of achieving pi:

    # 39 Characters
    map$x+=(-1)**$_*4/(2*$_+1),0..1e6;die$x

    Now, I know Ovid said no Trig functions, but I couldn't resist. Perhaps we could consider the next two examples mulligans :-)

    # 45 Characters
    use Math::Trig;die 16*atan(1/5)-4*atan(1/239)

    # 21 Characters
    use Math::Trig;die pi

    -Eric

    Update: Taking some of PrakashK's suggestions, shaved off a few more characters. Thanks PrakashK! :-)
      # 23 Characters
      use Math::Trig;warn pi;
      Why warn, when you can die saving one more character?
      # 22 Characters use Math::Trig;die pi;
      And, you can shave one more character, if you don't care for that pesky semi-colon at the end.

      Oh, never mind. We are not supposed to use trig functions.

      /prakash

        You can get the same result with 20 chars:
        die 3.14159265358979
        
        I found this trick in Logique, informatique et paradoxes, publisher Belin (Pour la Science), page 67, it was about the shorter program to get (not compute) pi with n digits.
      17 chars, if you're using trig:
        
      print 4*atan2 1,1
         MeowChow                                   
                     s aamecha.s a..a\u$&owag.print
(MeowChow) Re: Golf -- compute PI
by MeowChow (Vicar) on Apr 16, 2002 at 06:21 UTC
    36, obfuscated :)
      
    sub _{$---&&4/$----&_}print- _$-=1e5
    35, but emits a warning:
      
    sub _{$---&&4/$----&_}print-_$-=1e5
       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
Re: Golf -- compute PI
by pepik_knize (Scribe) on Apr 16, 2002 at 15:54 UTC
    Here's one using Archimedes's method that comes in at 67:

    $n=3;$s=1;for(1..9){$n*=2;$s=(2-(4-$s**2)**.5)**.5;$p=$n*$s}print$p

    As a side note, I had $_ instead of $p inside the curlies, but using just print outside didn't work, and I don't know why.

    Pepik

      Using $_ instead of $p is a nice try to save two strokes, but it fails because for(1..9){..} aliases elements of the range to $_, which overwrites your later use of $p. Good job, though.

      Cheers,
      Ovid

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      You could use $\ instead, which will trim the two chars at the expense of an 'uninitialized' warning....
      $n=3;$s=1;for(1..9){$n*=2;$s=(2-(4-$s**2)**.5)**.5;$\=$n*$s}print
      Infact, if you rearrange things and toss in a little obfu, you can trim a few more chars. It even has the side-effect of making it strict compliant:
      $@=3;$;=1;$@*=2,$;=(2-(4-$;**2)**.5)**.5,$\=$@*$;for 1..9;print

      -Blake

Re: Golf -- compute PI
by I0 (Priest) on Apr 17, 2002 at 16:14 UTC
    How about e:
    use integer;$|++;my@e=(1)x5e3;for(a..zzz){$e[$_-1]+=$e[$_]/$_,$e[$_]%= +$_ for reverse 1..$#e;print$e[0];$e[0]=0;$_*=10for@e;}
      Compute e to 1000 digits, 69 chars
      s!\w+!$%=($z=$&.0+$%)/($a=--$?||10);$z%$a!eg,print$%for(-1x65536)x1e3
Re: Golf -- compute PI
by Dr. Mu (Hermit) on Apr 22, 2002 at 07:00 UTC
    Here's a Monte Carlo prog that weighs in at 42:
    die grep(rand()**2+rand()**2<1,1..4e6)/1e6
    (I don't claim it's pretty, converges fast, scrimps on memory, or produces repeatable results.)
Re: Golf -- compute PI
by thospel (Hermit) on Mar 15, 2006 at 03:04 UTC
    Pi to 1000 digits: 77 strokes, by tybalt89 with a minor change by ton:
    ($c,@0)=map P|($c=$c%($d=10+20*$?).0+$_*$?)/$d,@0while$?-=@0[0,1e3]=3; +print@0

    78 strokes by ton:

    print!s!\w+!$\=($z=$&.0+$?--*$\)/++($b=2*$?||239)|0;$z%$b!egfor(-48x65 +536)x1e3

    Both can be extended for more digits

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://159377]
Approved by ChemBoy
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2014-11-01 06:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (228 votes), past polls