views:

3889

answers:

24
+75  Q: 

Code Golf - π day

The Challenge

Guidelines for code-golf on SO

The shortest code by character count to display a representation of a circle of radius R using the *character, followed by an approximation of π.

Input is a single number, R.

Since most computers seem to have almost 2:1 ratio you should only output lines where y is odd. This means that when R is odd you should print R-1 lines. There is a new testcase for R=13 to clarify.

eg.

Input
    5
Output      Correct                          Incorrect

        3    *******                    4      *******
        1   *********                   2     *********
       -1   *********                   0    ***********
       -3    *******                   -2     *********
           2.56                        -4      *******
                                            3.44

Edit: Due to widespread confusion caused by odd values of R, any solutions that pass the 4 test cases given below will be accepted

The approximation of π is given by dividing twice the number of * characters by .
The approximation should be correct to at least 6 significant digits.
Leading or trailing zeros are permitted, so for example any of 3, 3.000000, 003 is accepted for the inputs of 2 and 4.

Code count includes input/output (i.e., full program).

Test Cases

Input
    2
Output
     *** 
     *** 
    3.0

Input
    4
Output
      *****  
     ******* 
     ******* 
      *****  
    3.0

Input
    8
Output
         *******     
      *************  
     *************** 
     *************** 
     *************** 
     *************** 
      *************  
         *******     
    3.125

Input
    10
Output
          *********      
       ***************   
      *****************  
     ******************* 
     ******************* 
     ******************* 
     ******************* 
      *****************  
       ***************   
          *********      
    3.16

Bonus Test Case

Input
    13
Output

           *************       
        *******************    
       *********************   
      ***********************  
     ************************* 
     ************************* 
     ************************* 
     ************************* 
      ***********************  
       *********************   
        *******************    
           *************                                          
    2.98224852071
+11  A: 

C#: 209 202 201 characters:

using C=System.Console;class P{static void Main(string[]a){int r=int.Parse(a[0]),s=0,i,x,y;for(y=1-r;y<r;y+=2){for(x=1-r;x<r;s+=i)C.Write(" *"[i=x*x+++y*y<=r*r?1:0]);C.WriteLine();}C.Write(s*2d/r/r);}}

Unminified:

using C = System.Console;
class P {
  static void Main(string[] arg) {
    int r = int.Parse(arg[0]), sum = 0, inside, x, y;
    for (y = 1 - r; y < r; y += 2) {
      for (x = 1 - r; x < r; sum += inside)
        C.Write(" *"[inside = x * x++ + y * y <= r * r ? 1 : 0]);
      C.WriteLine();
    }
    C.Write(sum * 2d / r / r);
  }
}
Guffa
Nice trick, char[].
Dykam
I don't know C# very much but shouldn't you able to use `string[]a` and `1-r` (instead of `-1+r`)?
KennyTM
@Kenny: You are right. :) That saves three characters, and then I managed to get rid of five more.
Guffa
Spotted that first thing, totally missed on the `-r+1` thingy.
Dykam
Also, spotted `x*xx+++y*y` too, but it is a mad thing to dissect at first glance.
Dykam
I took the liberty of eliminating another byte ;-)
Joey
Nice one. Applied it to the non-compacted once too.
Dykam
Using goto I can get to 202 characters though... `a:[...]goto a;` But unable to eliminate the loose snippets from the for.
Dykam
+4  A: 

C++: 169 characters

#include <iostream>
int main(){int i,j,c=0,n;std::cin>>n;for(i=-n;i<=n;i+=2,std::cout<<'\n')for(j=-n;j<=n;j++)std::cout<<(i*i+j*j<=n*n?c++,'*':' ');std::cout<<2.*c/n/n;}

Unminified:

#include <iostream>
int main()
{
    int i,j,c=0,n;
    std::cin>>n;
    for(i=-n;i<=n;i+=2,std::cout<<'\n')
        for(j=-n;j<=n;j++)
            std::cout<<(i*i+j*j<=n*n?c++,'*':' ');
    std::cout<<2.*c/n/n;
}

(Yes, using std:: instead of using namespace std uses less characters)

The output here doesn't match the test cases in the original post, so here's one that does (written for readability). Consider it a reference implementation (if Poita_ doesn't mind):

#include <iostream>
using namespace std;

int main()
{
    int i, j, c=0, n;
    cin >> n;
    for(i=-n; i<=n; i++) {
        if (i & 1) {
            for(j=-n; j<=n; j++) {
                if (i*i + j*j <= n*n) {
                    cout << '*';
                    c++;
                } else {
                    cout << ' ';
                }
            }
            cout << '\n';
        }
    }
    cout << 2.0 * c / n / n << '\n';
}

C++: 168 characters (with output I believe is correct)

#include <iostream>
int main(){int i,j,c=0,n;std::cin>>n;for(i=-n|1;i<=n;i+=2,std::cout<<"\n")for(j=-n;j<=n;j++)std::cout<<" *"[i*i+j*j<=n*n&&++c];std::cout<<2.*c/n/n;}
Peter Alexander
The code loops from -n to n, so for an input of for example 4 it displays a diameter of 9, not 7 as shown in the test cases.
Guffa
Is it a requirement that your circle matches the OP's *exactly*?
Peter Alexander
@Poita_, Yes the asterisks should match exactly for the test cases given. Extra whitespace to the right doesn't matter though
gnibbler
You may wish to change it to `#include <iostream.h>` which basically is `#include <iostream> -- using namespace std;` for compatibility with old C++ compilers.
Earlz
Carlucho
@Carlos, I didn't write that particular bit, but it's a binary AND operator. It checks that the last bit is set, which is equivalent to doing `i%2`, but is "faster". It's not really faster because the compiler would do it anyway.
Peter Alexander
@Poita_: Thanks.
Carlucho
Joey Adams
gnibbler
You can save at least 8 characters if you use "#define o std::cout<<" and then replace all "std::cout<<" with "o "
Grant Peters
Wouldn't puts() give you 10 fewer characters?
Robert Davis
@Robert, no because that requires that you include stdlib.h.
Peter Alexander
@Poita That depends on the compiler/linker. GCC 4.3.3 does _not_ require _any_ includes to use `puts`. I can do it with `printf` too, but I actually get a warning [`int printf(const char*)` != int `printf(const char*,...)`]. Any undeclared c-function defaults to returning `int` and taking whatever arguments it is used with. The linker then has to figure out the implementation of `int puts(const char*)`. Since gcc always links against standard libs (unless -nostdlib) this is easy.
KitsuneYMG
Well I think it's only fair that the code does not depend on compiler idiosyncrasies.
Peter Alexander
+30  A: 

Perl, 95 96 99 106 109 110 119 characters:

$t+=$;=1|2*sqrt($r**2-($u-2*$_)**2),say$"x($r-$;/2).'*'x$;for 0..
($u=($r=<>)-1|1);say$t*2/$r**2

(The newline can be removed and is only there to avoid a scrollbar)

Yay! Circle version!

    $t+=$;=
 1|2*sqrt($r**
2-($u-2*$_)**2)
,say$"x($r-$;/2
).'*'x$;for 0..
($u=($r=<>)-1|1
 );$pi=~say$t*
    2/$r**2

For the uninitiated, the long version:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

# Read the radius from STDIN
my $radius = <>;

# Since we're only printing asterisks on lines where y is odd,
# the number of lines to be printed equals the size of the radius,
# or (radius + 1) if the radius is an odd number.
# Note: we're always printing an even number of lines.
my $maxline = ($radius - 1) | 1;

my $surface = 0;

# for ($_ = 0; $_ <= $maxline; $_++), if you wish
for (0 .. $maxline) {
    # First turn 0 ... N-1 into -(N/2) ... N/2 (= Y-coordinates),
    my $y = $maxline - 2*$_;

    # then use Pythagoras to see how many stars we need to print for this line.
    # Bitwise OR "casts" to int; and: 1 | int(2 * x) == 1 + 2 * int(x)
    my $stars = 1 | 2 * sqrt($radius**2-$y**2);
    $surface += $stars;    

    # $" = $LIST_SEPARATOR: default is a space,
    # Print indentation + stars 
    # (newline is printed automatically by say)
    say $" x ($radius - $stars/2) . '*' x $stars;
}

# Approximation of Pi based on surface area of circle:
say $surface*2/$radius**2;
mercator
That is by far the most unreadable code I've seen in my entire life
Chris Marisic
I guess you've never seen APL then.
Peter Wone
...or brainfuck...
lubos hasko
@Chris Marisic: Did you check the other questions/topics tagged `code-golf`? :) I've seen far more unreadable examples.
BalusC
@Peter:Unlike most, I've both seen and written APL. It takes a couple weeks to get accustomed to its special characters, but after that it can be quite readable. Even after a couple of decades to get accustomed, Perl is still much worse.
Jerry Coffin
I was only trying to be funny. I've always felt that Perl resembles nothing so much as line noise on a TTY. Some wag once dubbed it the world's first write-only language.
Peter Wone
So, is someone going to write an APL version then?
Nicholas Riley
111 chars, `$r=<>;$t+=$n=1+2*int sqrt($r**2-($u-2*$_)**2),print$"x($r-$n/2).'*'x$n.$/for(0..($u=$r-1+$r%2));print$t*2/$r**2`
Hasturkun
@Hasturkun: Updated. Nice use of `$"` and `$/`! I wouldn't have thought of that.
mercator
Using 'say' instead of print at the end of the loop would save the 3 characters used for printing newlines.
sundar
This version is currently printing the even rows when ever R is odd
gnibbler
@sundar, hmmm, I did think about that, but I tested it by saving it to file, which then requires a `use`... I'll leave it.
mercator
You can run it using `perl -M5.01`
gnibbler
@gnibbler, ah indeed, thanks... I'll have to think about the odd R tonight. I thought it was printing the right number of lines, though. The origin is in the center, between the middle two lines. Doesn't that mean that, for R=13, the top and bottom should be at (0,13) and (0,-13), making a total of 14 odd lines? Your example output only has 12 lines.
mercator
@mercator, Since I am printing '*' only for points inside the circle the top and bottom line would be blank. You can do 14 lines if you like, the blank lines are optional.
gnibbler
To this day, Perl appears to be the most compressible language on planet Earth.
flq
@mercator, I've decided to make the odd number test case optional as it raises too many issues and violates the "fun" principle
gnibbler
Change `$n` to some writable and inscrutable variable like `$;`. Then you can remove the space before `for`.
mobrule
So the C version is almost as short? So much for writing unreadable but compact Perl code I guess...
Amigable Clark Kant
@mobrule - Ooh, thanks!
mercator
@gnibbler, I don't want to shoot down my own answer now, but what exactly are the issues with the odd numbers? The only issue I can see is whether it's okay to print stars on the circle itself too or not. That isn't made clear in the challenge and I didn't think about it until your comments. That issue only happens to occur on odd radiuses because of (0, ±R) and Pythagorean triples (http://mathworld.wolfram.com/PythagoreanTriple.html) such as (±12, ±5) on the R=13 circle.
mercator
@mercator, yeah, you are pretty spot on, and since there wasn't originally a testcase with a triple, it didn't seem fair to me to add extra conditions that would break answers already submitted. Especially as other people were basing their answers on existing ones.
gnibbler
@gnibbler: instead of -M5.01, you can do -E instead. Save you four characters, if you pass it all on the command line. :)
Robert P
+9  A: 

HyperTalk: 237 characters

Indentation is not required nor counted. It is added for clarity. Also note that HyperCard 2.2 does accept those non-ASCII relational operators I used.

function P R
  put""into t
  put 0into c
  repeat with i=-R to R
    if i mod 2≠0then
      repeat with j=-R to R
        if i^2+j^2≤R^2then
          put"*"after t
          add 1to c
        else
          put" "after t
        end if
      end repeat
      put return after t
    end if
  end repeat
  return t&2*c/R/R
end P

Since HyperCard 2.2 doesn't support stdin/stdout, a function is provided instead.

Joey Adams
Hypercard, Mr. Adams? Seriously? This is highly unexpected.
Kawa
@Kawa: That's kind of why I posted it :) Also, code golf is a good way to build up a test suite in case I decide to write a HyperTalk interpreter in the future.
Joey Adams
@Joey Adams: Hah! I'd like to see that, XD
Kawa
+92  A: 

C: 131 chars

(Based on the C++ solution by Joey)

main(i,j,c,n){for(scanf("%d",&n),c=0,i|=-n;i<n;puts(""),i+=2)for(j=-n;++j<n;putchar(i*i+j*j<n*n?c++,42:32));printf("%g",2.*c/n/n);}

(Change the i|=-n to i-=n to remove the support of odd number cases. This merely reduces char count to 130.)

As a circle:

      main(i,j,
   c,n){for(scanf(
  "%d",&n),c=0,i=1|
 -n;i<n;puts(""),i+=
 0x2)for(j=-n;++j<n;
 putchar(i*i+j*j<n*n
 ?c++,0x02a:0x020));
  printf("%g",2.*c/
   n/n);3.1415926;
      5358979;}
KennyTM
Sweet formatting.
Dykam
I like how you added circles to the code to turn it into a circle. Would +000 be preferable?
Potatoswatter
congratulations, j*j++ is undefined behaviour
sellibitze
@sellibitze: Ah right. The update should have removed the undefined behavior (and eliminated the odd-number bug.)
KennyTM
wasn't this an IOCCC winner?
Adriano Varoli Piazza
There's an IOCCC entry very much along these lines. It approximates pi by counting its own characters, shaped in a circle.
Joey Adams
Can be down 2 chars if you turn <= into a > comparison.
Jasper Bekkers
wouldn't that only be one character...?
Wallacoloo
No because he compares with <= twice.
Jasper Bekkers
@Jasper: How? The `i<=n` must be like that due to the `for` loop, the `i*i+j*j<=n*n` must be like that otherwise the `c++,42` expression needs parenthesis.
KennyTM
You can just write `n>i` and `n*n>i*i+j*j` they mean the same thing.
Jasper Bekkers
How does `main()` take four `int` arguments?
Loadmaster
@Load: 5.1.2.2.1/1: The function called at program startup is named `main`. It shall be defined … *or in some other implementation-defined manner*. So that's because the implementation can accept this form.
KennyTM
If there are no command line args, `i=1` already, so you can say `i|=-n`
gnibbler
@KennyTM: Using a non-standard `main()` renders the program non-portable. Is that what you intended?
Loadmaster
+4  A: 

Python: 118 characters

Pretty much a straightforward port of the Perl version.

r=input()
u=r+r%2
t=0
for i in range(u):n=1+2*int((r*r-(u-1-2*i)**2)**.5);t+=n;print' '*(r-n/2-1),'*'*n
print 2.*t/r/r
Nicholas Riley
For python2 you can just use `r=input()`
gnibbler
You don't need the space between `print` and `' '`
gnibbler
OK, that's scary, it's shorter than the Perl version now. (I completely put "input" out of my mind because it's so unsafe ordinarily...)
Nicholas Riley
@Nicholas: Not anymore :-P
mercator
+7  A: 

Haskell 139 145 147 150 230 chars:

x True=' ';x _='*'
a n=unlines[[x$i^2+j^2>n^2|j<-[-n..n]]|i<-[1-n,3-n..n]]
b n=a n++show(sum[2|i<-a n,i=='*']/n/n)
main=readLn>>=putStrLn.b

Handling the odd numbers: 148 chars:

main=do{n<-readLn;let{z k|k<n^2='*';z _=' ';c=[[z$i^2+j^2|j<-[-n..n]]|i<-[1,3..n]];d=unlines$reverse c++c};putStrLn$d++show(sum[2|i<-d,i=='*']/n/n)}

150 chars: (Based on the C version.)

a n=unlines[concat[if i^2+j^2>n^2then" "else"*"|j<-[-n..n]]|i<-[1-n,3-n..n]]
main=do n<-read`fmap`getLine;putStr$a n;print$2*sum[1|i<-a n,i=='*']/n/n

230 chars:

main=do{r<-read`fmap`getLine;let{p=putStr;d=2/fromIntegral r^2;l y n=let c m x=if x>r then p"\n">>return m else if x*x+y*y<r*r then p"*">>c(m+d)(x+1)else p" ">>c m(x+1)in if y>r then print n else c n(-r)>>=l(y+2)};l(1-r`mod`2-r)0}

Unminified:

main = do r <- read `fmap` getLine
          let p = putStr
              d = 2/fromIntegral r^2
              l y n = let c m x = if x > r
                                  then p "\n" >> return m
                                  else if x*x+y*y<r*r
                                       then p "*" >> c (m+d) (x+1)
                                       else p " " >> c m (x+1)
                      in if y > r
                         then print n
                         else c n (-r) >>= l (y+2)
          l (1-r`mod`2-r) 0

I was kinda hoping it would beat some of the imperative versions, but I can't seem to compress it any further at this point.

Steve
Chopped off 2 more by getting rid of the "d" and adding 1 instead of it and then printing "2*n/fromIntegral r^2"
Steve
Shaved 3 characters off via a few Haskell tricks. I love that in Haskell there is often no cost to multiple lines (newline vs. semicolon) and hence our code-golf is generally readable!
MtnViewMark
Strictly speaking, the 145-char version only works if the input is even. But very nice either way.
Steve
Shortened the I/O line. It should still be possible to save a few more characters by pushing the function defs into a main=do{...let{...}...} block, I think.
comingstorm
@comingstorm: Cool! I didn't know about readLn. This will help many a Haskell code-golf.@Steve: Yup, I'm still trying to figure out the most efficient way to fix that.
MtnViewMark
+8  A: 

Ruby, 96 chars

(based on Guffa's C# solution):

r=gets.to_f
s=2*t=r*r
g=1-r..r
g.step(2){|y|g.step{|x|putc' * '[i=t<=>x*x+y*y];s+=i}
puts}
p s/t

109 chars (bonus):

r=gets.to_i
g=-r..r
s=g.map{|i|(g.map{|j|i*i+j*j<r*r ?'*':' '}*''+"\n")*(i%2)}*''
puts s,2.0/r/r*s.count('*')
Mladen Jablanović
(1..2*r=gets.to_f) for reading from stdin
gnibbler
Thanks! I'm embarrassed to see how unreadable Ruby can be... :)
Mladen Jablanović
you can also use `p s` instead of `puts s` :)
gnibbler
cool, thanks! ;)
Mladen Jablanović
Nice fresh ideas in there - I like that you are using g with 2 different step sizes and the <=> to avoid having code to convert from logical
gnibbler
+19  A: 

Python: 101 104 107 110 chars

Based on the other Python version by Nicholas Riley.

r=input()
t=0
i=1
exec"n=1+int((2*i*r-i*i)**.5)*2;t+=2.*n/r/r;print' '*(r-n/2)+'*'*n;i+=2;"*r
print t

Credits to AlcariTheMad for some of the math.


Ah, the odd-numbered ones are indexed with zero as the middle, explains everything.

Bonus Python: 115 chars (quickly hacked together)

r=input()
t=0
i=1
while i<r*2:n=1+int((2*i*r-i*i)**.5)*2;t+=2.*n/r/r;print' '*(r-n/2)+'*'*n;i+=2+(r-i==2)*2
print t

Python: 61 chars

exec __import__('urllib').urlopen('http://301.to/j4h').read()

lunixbochs
Wow, yeah, '+' beats -1 and , any day. Yet another technique I put out of my mind because it's almost never the right thing to do :-)
Nicholas Riley
I've used C in the past, and never even looked at Python. This 104 chars is more readable than the C++ above. Amazing. Maybe I should learn Python...
Dean
@Dean: One of the main goals of Python is to be easy to read and write.
AlcariTheMad
have you though about using exec with your 104 char answer too? :)
gnibbler
I would need to roll my own compression - zlib, marshalling, etc all came out larger than the actual code.
lunixbochs
how about just using exec instead of the while loop? ;)
gnibbler
We considered taking the compiled code object+marshal+zlib+base64 and exec that, but the result is around 350 chars. In fact, the bytecode python uses is longer than the source code itself.
AlcariTheMad
There it is :) +1
gnibbler
+10  A: 

Powershell, 119 113 109 characters

($z=-($n=$args[($s=0)])..$n)|?{$_%2}|%{$l="";$i=$_
$z|%{$l+=" *"[$i*$i+$_*$_-lt$n*$n-and++$s]};$l};2*$s/$n/$n

and here's a prettier version:

( $range = -( $R = $args[ ( $area = 0 ) ] ) .. $R ) | 
  where { $_ % 2 } |
  foreach {
    $line = ""
    $i = $_
    $range | foreach {
        $line += " *"[ $i*$i + $_*$_ -lt $R*$R -and ++$area ]
    }
    $line
 }
 2 * $area / $R / $R
Danko Durbić
Is all Powershell code this ugly? ;)
Thor
@Thor: I hope not, but this must be the ugliest thing I've ever written :)
Danko Durbić
@Danko: Thanks for that prettier version =)
Thor
@Thor: You're welcome!
Danko Durbić
+23  A: 

FORTRAN - 101 Chars

$ f95 piday.f95 -o piday && echo 8 | ./piday

READ*,N
DO I=-N,N,2
M=(N*N-I*I)**.5
PRINT*,(' ',J=1,N-M),('*',J=0,M*2)
T=T+2*J
ENDDO
PRINT*,T/N/N
END


    READ*,N
  K=N/2*2;DO&
 I=1-K,N,2;M=&
(N*N-I*I)**.5;;
PRINT*,(' ',J=&
1,N-M),('*',J=&
0,M*2);T=T+2*J;
 ENDDO;PRINT*&
  ,T/N/N;END;
    !PI-DAY
gnibbler
FORTRAN is competitive on this code golf! Well done.
John at CashCommons
Wait, I though formatting was important in Fortran? You have letters in column 1!
Joel
@Joel, Fortran95 allows free-form code
gnibbler
Most people are still stuck on Fortan77 from what I've seen.
Joel
@Joel, Fortran77 is not a good language for code-golf :)
gnibbler
Is Fortran 77 a good language for anything? LOL
Joel
+15  A: 

x86 Machine Code: 127 bytes

Intel Assembler: 490 chars

    mov si,80h
    mov cl,[si]
    jcxz ret
    mov bx,10
    xor ax,ax
    xor bp,bp
    dec cx
  a:mul bx
    mov dl,[si+2]
    sub dl,48
    cmp dl,bl
    jae ret
    add ax,dx
    inc si
    loop a
    mov dl,al
    inc dl
    mov dh,al
    add dh,dh
    mov ch,dh
    mul al
    mov di,ax
  x:mov al,ch
    sub al,dl
    imul al
    mov si,ax
    mov cl,dh
  c:mov al,cl
    sub al,dl
    imul al
    add ax,si
    cmp ax,di
    mov al,32
    ja y
    or al,bl
    add bp,2
  y:int 29h
    dec cl
    jnz c
    mov al,bl
    int 29h
    mov al,13
    int 29h
    sub ch,2
    jnc x
    mov ax,bp
    cwd
    mov cl,7
  e:div di
    cmp cl,6
    jne z
    pusha
    mov al,46
    int 29h
    popa
  z:add al,48
    int 29h
    mov ax,bx
    mul dx
    jz ret
    dec cl
    jnz e
    ret

This version handles the bonus test case as well and is 133 bytes:

    mov si,80h
    mov cl,[si]
    jcxz ret
    mov bx,10
    xor ax,ax
    xor bp,bp
    dec cx
  a:mul bx
    mov dl,[si+2]
    sub dl,48
    cmp dl,bl
    jae ret
    add ax,dx
    inc si
    loop a
    mov dl,al
    rcr dl,1
    adc dl,dh
    add dl,dl
    mov dh,dl
    add dh,dh
    dec dh
    mov ch,dh
    mul al
    mov di,ax
  x:mov al,ch
    sub al,dl
    imul al
    mov si,ax
    mov cl,dh
  c:mov al,cl
    sub al,dl
    imul al
    add ax,si
    cmp ax,di
    mov al,32
    jae y
    or al,bl
    add bp,2
  y:int 29h
    dec cl
    jnz c
    mov al,bl
    int 29h
    mov al,13
    int 29h
    sub ch,2
    jnc x
    mov ax,bp
    cwd
    mov cl,7
  e:div di
    cmp cl,6
    jne z
    pusha
    mov al,46
    int 29h
    popa
  z:add al,48
    int 29h
    mov ax,bx
    mul dx
    jz ret
    dec cl
    jnz e
    ret
Skizz
I love StackOverflow!
zengr
It's interesting that some of the high level languages have shorter character counts than the binary this produces.
AlcariTheMad
@Alcari: If you included all the code in the libraries the higher level languages use, their character counts would be significantly higher. In assembler, doing `printf("%f",a/b)` is not trivial, there's no single instruction to do that, and my implementation above assumes that 0 <= a/b < 10 and that the operation is a division and that a and b are integers.
Skizz
+3  A: 

PHP: 126 132 138

(based on Guffa C# solution)

126:

for($y=1-($r=$argv[1]);$y<$r;$y+=2,print"\n")for($x=1-$r;$x<$r;$s+=$i,++$x)echo($i=$x*$x+$y*$y<=$r*$r)?'*':' ';echo$s*2/$r/$r;

132:

for($y=1-($r=$argv[1]);$y<$r;$y+=2){for($x=1-$r;$x<$r;@$s+=$i,++$x)echo($i=$x*$x+$y*$y<=$r*$r?1:0)?'*':' ';echo"\n";}echo$s*2/$r/$r;

138:

for($y=1-($r=$argv[1]);$y<$r;$y+=2){for($x=1-$r;$x<$r;@$s+=$i){$t=$x;echo($i=$t*$x++ +$y*$y<=$r*$r?1:0)?'*':' ';}echo"\n";}echo$s*2/$r/$r;

Current full:

for( $y = 1 - ( $r = $argv[1]); $y < $r; $y += 2, print "\n")
    for( $x = 1-$r; $x < $r; $s += $i, ++$x)
        echo( $i = $x*$x + $y*$y <= $r*$r) ? '*' : ' ';
echo $s*2 /$r /$r;

Can be without @ before first $s but only with error_reporting set to 0 (Notice outputs is messing the circle)

dev-null-dweller
what does the /$r do in echo $s*2 /$r /$r;
davidosomething
$s*2/$r/$r = $s*2/($r*$r)
Jasper Bekkers
OHH division... the spacing threw me off, thought it was some operator shorthand i'd never seen
davidosomething
+41  A: 

XSLT 1.0

Just for fun, here's an XSLT version. Not really code-golf material, but it solves the problem in a weird-functional-XSLT-kind of way :)

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" >
  <xsl:output method="html"/>

  <!-- Skip even lines -->
  <xsl:template match="s[@y mod 2=0]">
    <xsl:variable name="next">
      <!-- Just go to next line.-->
      <s R="{@R}" y="{@y+1}" x="{-@R}" area="{@area}"/>
    </xsl:variable>
    <xsl:apply-templates select="msxsl:node-set($next)"/>
  </xsl:template>

  <!-- End of the line?-->
  <xsl:template match="s[@x &gt; @R]">
    <xsl:variable name="next">
      <!-- Go to next line.-->
      <s R="{@R}" y="{@y+1}" x="{-@R}" area="{@area}"/>
    </xsl:variable><!-- Print LF-->&#10;<xsl:apply-templates 
      select="msxsl:node-set($next)"/>
  </xsl:template>

  <!-- Are we done? -->
  <xsl:template match="s[@y &gt; @R]">
    <!-- Print PI approximation -->
    <xsl:value-of select="2*@area div @R div @R"/>
  </xsl:template>

  <!-- Everything not matched above -->
  <xsl:template match="s">
    <!-- Inside the circle?-->
    <xsl:variable name="inside" select="@x*@x+@y*@y &lt; @R*@R"/>
    <!-- Print "*" or " "-->
    <xsl:choose>
      <xsl:when test="$inside">*</xsl:when>
      <xsl:otherwise>&#160;</xsl:otherwise>
    </xsl:choose>

    <xsl:variable name="next">
      <!-- Add 1 to area if we're inside the circle. Go to next column.-->
      <s R="{@R}" y="{@y}" x="{@x+1}" area="{@area+number($inside)}"/>
    </xsl:variable>
    <xsl:apply-templates select="msxsl:node-set($next)"/>
  </xsl:template>

  <!-- Begin here -->
  <xsl:template match="/R">
    <xsl:variable name="initial">
      <!-- Initial state-->
      <s R="{number()}" y="{-number()}" x="{-number()}" area="0"/>
    </xsl:variable>
    <pre>
      <xsl:apply-templates select="msxsl:node-set($initial)"/>
    </pre>
  </xsl:template>
</xsl:stylesheet>

If you want to test it, save it as pi.xslt and open the following XML file in IE:

<?xml version="1.0"?> 
<?xml-stylesheet href="pi.xslt" type="text/xsl" ?> 
<R> 
  10 
</R> 
Danko Durbić
my <eyes></eyes>! The goggles, they <do>nothing</do>!
Jimmy
+1 crazy one. Your xmls should look fantastic
Matias
Dang! I'm afraid you may have beaten my HyperCard solution for uniqueness :D
Joey Adams
I can't believe you said "open...IE"
harpo
Heh, yes, back in the day, we only had IE and XML with XSLT was the solution to all our problems. Good old times! :)
Danko Durbić
XSL version 1.0 wow, I remember looking forward to version 2 but by the time it came out I'd already moved on.
gradbot
+2  A: 

You guys are thinking way too hard.

switch (r) {
   case 1,2:
      echo "*"; break;
   case 3,4:
      echo " ***\n*****\n ***"; break;
   // etc.
}
Matt Huggins
Character count gets a bit out of hand, don't you think? :)
gnibbler
Doesn't scale. Unmaintainable!
spoulson
I tried compressing the test case cheat as much as possible and it still ended up slightly larger than my actual solution :P
lunixbochs
+1, always do the most obvious thing first... if someone doesnt like it, loudly complain that the spec wasnt clear enough
mizipzor
Brian had a semi-serious attempt at special casing the test cases, you should upvote his too if you like this answer ;) http://stackoverflow.com/questions/2457995
gnibbler
+6  A: 

PHP: 117

Based on dev-null-dweller

for($y=1-$r=$argv[1];$y<$r;$y+=2,print"\n")for($x=1-$r;$x<$r;$x++)echo$r*$r>$x*$x+$y*$y&&$s++?'*':' ';echo$s*2/$r/$r;
Jasper Bekkers
+1  A: 

JavaScript (SpiderMonkey) - 118 chars

This version accepts input from stdin and passes the bonus test cases

r=readline()
for(t=0,i=-r;i<r;i++)if(i%2){for(s='',j=-r;j<r;j++){t+=q=i*i+j*j<r*r
s+=q?'*':' '}print(s)}print(t*2/r/r)

Usage: cat 10 | js thisfile.js -- jsbin preview adds an alias for print/readline so you can view in browser

Javascript: 213 163


Updated

r=10;m=Math;a=Array;t=0;l=document;for(i=-r;i<r;i+=2){w=m.floor(m.sqrt(r*r-i*i)*2);t+=w*2;l.writeln(a(m.round(r-w/2)).join(' ')+a(w).join('*'));}l.writeln(t/(r*r))

Nobody said it had to render correctly in the browser - just the output. As such I've removed the pre tags and optimised it further. To view the output you need to view generated source or set your stylesheet accordingly. Pi is less accurate this way, but it's now to spec.


r=10;m=Math;a=Array;t=0;s='';for(i=-r;i<r;i++){w=m.floor((m.sqrt(m.pow(r,2)-m.pow(i,2)))*2);t+=w;if(i%2){z=a(m.round(r-w/2)).join(' ')+a(w).join('*');s+=z+'\n';}}document.write('<pre>'+(s+(t/m.pow(r,2)))+'</pre>')

Unminified:

r=10;
m=Math;
a=Array;
t=0;
s='';
for(i=-r;i<r;i++){
    w=m.floor((m.sqrt(m.pow(r,2)-m.pow(i,2)))*2);
    t+=w;
    if(i%2){
    z=a(m.round(r-w/2)).join(' ')+a(w).join('*');
    s+=z+'\n';
    }
}
document.write('<pre>'+(s+(t/m.pow(r,2)))+'</pre>');
Iain Fraser
+1  A: 

Java: 234

class C{public static void main(String[] a){int x,y,s=0,r=Integer.parseInt(a[0]);for(y=1-r;y<r;y+=2){for(x=1-r;x<r;++x){boolean b=x*x+y*y<=r*r;s+=b?1:0;System.out.print(b?'*':' ');}System.out.println();}System.out.println(s*2d/r/r);}}

Unminified:

class C{
    public static void main(String[] a){
        int x,y,s=0,r=Integer.parseInt(a[0]); 
        for(y=1-r;y<r;y+=2){
            for(x=1-r;x<r;++x) {
                boolean b=x*x+y*y<=r*r;
                s+=b?1:0;
                System.out.print(b?'*':' ');
            }
            System.out.println();
        }
        System.out.println(s*2d/r/r);
    }
}
dogbane
+7  A: 

In dc: 88 and 93 93 94 96 102 105 129 138 141 chars

Just in case, I am using OpenBSD and some supposedly non-portable extensions at this point.

93 chars. This is based on same formula as FORTRAN solution (slightly different results than test cases). Calculates X^2=R^2-Y^2 for every Y

[rdPr1-d0<p]sp1?dsMdd*sRd2%--
[dd*lRr-vddlMr-32rlpxRR42r2*lpxRRAP4*2+lN+sN2+dlM>y]
dsyx5klNlR/p

88 chars. Iterative solution. Matches test cases. For every X and Y checks if X^2+Y^2<=R^2

1?dsMdd*sRd2%--sY[0lM-[dd*lYd*+lRr(2*d5*32+PlN+sN1+dlM!<x]dsxxAPlY2+dsYlM>y]
dsyx5klNlR/p

To run dc pi.dc.

Here is an older annotated version:

# Routines to print '*' or ' '. If '*', increase the counter by 2
[lN2+sN42P]s1
[32P]s2
# do 1 row
# keeping I in the stack
[
 # X in the stack
 # Calculate X^2+Y^2 (leave a copy of X)
 dd*lYd*+ 
 #Calculate X^2+Y^2-R^2...
 lR-d
 # .. if <0, execute routine 1 (print '*')
 0>1
 # .. else execute routine 2 (print ' ')
 0!>2 
 # increment X..
 1+
 # and check if done with line (if not done, recurse)
 d lM!<x
]sx
# Routine to cycle for the columns
# Y is on the stack
[
  # push -X
  0lM- 

  # Do row
  lxx 
  # Print EOL
  10P
  # Increment Y and save it, leaving 2 copies
  lY 2+ dsY 
  # Check for stop condition
  lM >y
]sy
# main loop
# Push Input value
[Input:]n?
# Initialize registers
# M=rows
d sM
# Y=1-(M-(M%2))
dd2%-1r-sY
# R=M^2
d*sR
# N=0
0sN
[Output:]p
# Main routine
lyx
# Print value of PI, N/R
5klNlR/p
Dan Andreatta
+1 For less than 100 chars. I'll delete my dc answer
Carlos Gutiérrez
Doesn't work with linux dc, but I **can confirm it works on openbsd**. Awesome!
gnibbler
@Carlos, yes the `(` operator sure is handy. too bad it remains unimplemented in the dc that comes with linux
gnibbler
@gnibbler - "A complete rewrite of the dc command using the bn(3) big number routines first appeared in OpenBSD 3.5." I didn't know that. Some nice new operators are included, but they are marked as "non-portable extensions".
Carlos Gutiérrez
Yeah, the ( operator alone allowed to shed 6 strokes!
Dan Andreatta
+2  A: 

And a bash entry: 181 186 190 chars

for((y=-(r=$1,r/2*2);y<=r;y+=2));do for((x=-r;x<=r;++x));do((x*x+y*y<r*r))&&{((++n));echo -n '*';}||echo -n " ";((x<r))||echo;done;done;((s=1000,p=n*2*s/r/r,a=p/s,b=p%s));echo $a.$b

Run with e.g. bash py.sh 13

Dan Andreatta
+1  A: 

GAWK: 136, 132, 126, 125 chars

Based on the Python version.

{r=$1
for(i=-1;r*2>i+=2;print""){n=1+int((2*i*r-i*i)**.5)*2
t+=2*n/r/r
printf"%*s",r-n/2,""
while(n--)printf"%c","*"}print t}
przemoc
Only the first result is correct now.
przemoc
+1  A: 

Python: 148 characters.

Failed (i.e. not short enough) attempt to abuse the rules and hardcode the test cases, as I mentioned in reply to the original post. Abusing it with a more verbose language may have been easier:

a=3.0,3.125,3.16
b="1","23","3677","47899"
r=input()
for i in b[r/3]+b[r/3][::-1]:q=1+2*int(i);print ' '*(int(b[r/3][-1])-int(i))+'*'*q
print a[r/5]
Brian
+2  A: 

bc: 165, 127, 126 chars

Based on the Python version.

r=read()
for(i=-1;r*2>i+=2;scale=6){n=sqrt(2*i*r-i*i)
scale=0
n=1+n/1*2
j=r-n/2
t+=2*n
while(j--)" "
while(n--)"*"
"
"}
t/r/r

(New line after the last line cannot be omitted here.)

przemoc
127 chars: r=read();for(i=1;i<r*2;scale=6){n=sqrt(2*i*r-i*i);scale=0;n=1+n/1*2;i+=2;j=r-n/2;t+=2*n;while(j--)" ";while(n--)"*";""};t/r/r
Carlos Gutiérrez
@Carlos Gutiérrez: Nice shortening, thanks!
przemoc
The only problem here is that it now fails for 0, but according to current rules, it's ok.
przemoc
+1  A: 

Ruby 1.8.x, 93

r=$_.to_f
q=0
e=r-1
(p(('*'*(n=1|2*(r*r-e*e)**0.5)).center r+r)
q+=n+n
e-=2)while-r<e
p q/r/r

Run with $ ruby -p piday

DigitalRoss
Nice one, but it doesn't print out the pi approximation
gnibbler
Fixed now. Just saw the code-golf today.
DigitalRoss
It doesn't work in 1.9.1, and prints double quotes around the circle.
Mladen Jablanović
It's normal for golf programs not to work on a wildly different language levels. How many Perl or Python c-g's work on every version of the language? It is interesting, though, turns out the reason is because `Integer|Float` no longer coerces the float on 1.9.
DigitalRoss