95
votes

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 R2.
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
13
  • You may wish to clarify whether the "input" is on the command line, or on stdin. Commented Mar 13, 2010 at 23:15
  • 1
    @Greg Hewgill, Feel free to choose whichever is most convenient for the language you are using :) Commented Mar 13, 2010 at 23:21
  • @Greg Hewgill, Some (that is, very few) programming language implementations do not have a notion of "command line". Commented Mar 14, 2010 at 3:49
  • 1
    I notice that few of the answers follow the rule of only putting out lines where y is odd. Given an odd value of r (not shown in the test cases), most will output lines where y is even! Commented Mar 15, 2010 at 5:55
  • 6
    Rule abuse challenge: Make code that is shorter than anyone else's code by only supporting the 4 required test cases. Commented Mar 16, 2010 at 18:35

26 Answers 26

119
votes

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;}
Sign up to request clarification or add additional context in comments.

13 Comments

I like how you added circles to the code to turn it into a circle. Would +000 be preferable?
congratulations, j*j++ is undefined behaviour
wouldn't that only be one character...?
How does main() take four int arguments?
@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.
|
46
votes

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> 

5 Comments

my <eyes></eyes>! The goggles, they <do>nothing</do>!
Dang! I'm afraid you may have beaten my HyperCard solution for uniqueness :D
I can't believe you said "open...IE"
Heh, yes, back in the day, we only had IE and XML with XSLT was the solution to all our problems. Good old times! :)
XSL version 1.0 wow, I remember looking forward to version 2 but by the time it came out I'd already moved on.
35
votes

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;

22 Comments

That is by far the most unreadable code I've seen in my entire life
I guess you've never seen APL then.
@Chris Marisic: Did you check the other questions/topics tagged code-golf? :) I've seen far more unreadable examples.
@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.
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
|
25
votes

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

3 Comments

Wait, I though formatting was important in Fortran? You have letters in column 1!
Most people are still stuck on Fortan77 from what I've seen.
I like how the circle version looks like the Death Star.
22
votes

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

2 Comments

It's interesting that some of the high level languages have shorter character counts than the binary this produces.
@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.
19
votes

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

7 Comments

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 :-)
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: One of the main goals of Python is to be easy to read and write.
have you though about using exec with your 104 char answer too? :)
I would need to roll my own compression - zlib, marshalling, etc all came out larger than the actual code.
|
15
votes

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

4 Comments

Doesn't work with linux dc, but I can confirm it works on openbsd. Awesome!
@Carlos, yes the ( operator sure is handy. too bad it remains unimplemented in the dc that comes with linux
@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".
Yeah, the ( operator alone allowed to shed 6 strokes!
12
votes

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

1 Comment

@Thor: I hope not, but this must be the ugliest thing I've ever written :)
10
votes

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.

4 Comments

Hypercard, Mr. Adams? Seriously? This is highly unexpected.
@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.
Hah! I'd like to see that, XD
If you ever decide to write that interpreter, or want to join work on an existing one, let me know and I can add mention of it on hypercard.org and I'd be curious about how it goes :-)
10
votes

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);
 }
}

7 Comments

I don't know C# very much but shouldn't you able to use string[]a and 1-r (instead of -1+r)?
@Kenny: You are right. :) That saves three characters, and then I managed to get rid of five more.
Spotted that first thing, totally missed on the -r+1 thingy.
Also, spotted x*xx+++y*y too, but it is a mad thing to dissect at first glance.
I took the liberty of eliminating another byte ;-)
|
10
votes

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;print2ドル*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.

7 Comments

Chopped off 2 more by getting rid of the "d" and adding 1 instead of it and then printing "2*n/fromIntegral r^2"
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!
Strictly speaking, the 145-char version only works if the input is even. But very nice either way.
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: 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.
|
10
votes

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('*')

3 Comments

Thanks! I'm embarrassed to see how unreadable Ruby can be... :)
you can also use p s instead of puts s :)
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
9
votes

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;

Comments

8
votes

You guys are thinking way too hard.

switch (r) {
 case 1,2:
 echo "*"; break;
 case 3,4:
 echo " ***\n*****\n ***"; break;
 // etc.
}

5 Comments

Character count gets a bit out of hand, don't you think? :)
Doesn't scale. Unmaintainable!
I tried compressing the test case cheat as much as possible and it still ended up slightly larger than my actual solution :P
+1, always do the most obvious thing first... if someone doesnt like it, loudly complain that the spec wasnt clear enough
Brian had a semi-serious attempt at special casing the test cases, you should upvote his too if you like this answer ;) stackoverflow.com/questions/2457995
7
votes

J: (削除) 47 (削除ここまで), (削除) 46 (削除ここまで), 45

Same basic idea as other solutions, i.e. r^2 <= x^2 + y^2, but J's array-oriented notation simplifies the expression:

c=:({&' *',&":2*+/@,%#*#)@:>_2{.\|@j./~@i:@<:

You'd call it like c 2 or c 8 or c 10 etc.

Bonus: 49

To handle odd input, e.g. 13, we have to filter on odd-valued x coordinates, rather than simply taking every other row of output (because now the indices could start at either an even or odd number). This generalization costs us 4 characters:

c=:*:({&' *'@],&":2%(%+/@,))]>(|@j./~2&|#])@i:@<:

Deminimized version:

c =: verb define
 pythag =. y > | j./~ i:y-1 NB. r^2 > x^2 + y^2
 squished =. _2 {.\ pythag NB. Odd rows only
 piApx =. (2 * +/ , squished) % y*y
 (squished { ' *') , ": piApx
)

Improvements and generalizations due to Marshall Lochbam on the J Forums.

Comments

5
votes

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

3 Comments

For python2 you can just use r=input()
You don't need the space between print and ' '
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...)
4
votes

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;}

13 Comments

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.
Is it a requirement that your circle matches the OP's exactly?
You may wish to change it to #include <iostream.h> which basically is #include <iostream> -- using namespace std; for compatibility with old C++ compilers.
@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.
@Poita_: Actually, i%2 and i&1 behave differently with negative numbers. (-1)&1 is 1, which is what we want here. (-1)%2 is -1 on my system, and this conforms to C99. Thus, although if (i&1) and if (i%2) will do the same thing, one must be careful with if (i%2 == 1), which won't work when i is negative.
|
3
votes

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)

2 Comments

what does the /$r do in echo $s*2 /$r /$r;
OHH division... the spacing threw me off, thought it was some operator shorthand i'd never seen
3
votes

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

3 Comments

Nice one, but it doesn't print out the pi approximation
It doesn't work in 1.9.1, and prints double quotes around the circle.
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.
3
votes

APL: 59

This function accepts a number and returns the two expected items. Works correctly in bonus cases.

{⍪(⊂' *'[1+m])×ばつ+/,m←(2|v)⌿(q←⍵*2)&g×ばつ⍵-1}

Dialect is Dyalog APL, with default index origin. Skill level is clueless newbie, so if any APL guru wants to bring it down to 10 characters, be my guest!


You can try it online on Try APL, just paste it in and put a number after it:

 {⍪(⊂' *'[1+m])×ばつ+/,m←(2|v)⌿(q←⍵*2)&g×ばつ⍵-1} 13
 *************
 *******************
 *********************
 ***********************
*************************
*************************
*************************
*************************
 ***********************
 *********************
 *******************
 *************
2.98225

2 Comments

Although I dont know APL, It looks prettier than the J version.
@ahala Indeed. APL is beautiful, both conceptually and aesthetically. I started learning J, but was turned off by the random ASCII craziness. A good soul wrote an open source APL interpreter for Node.js (npm install apl) that's pretty good. It computes the above code with just a minor change (no monadic , 2nd char.) You can find good APL documentation on all vendor sites, such as Dyalog.
2
votes

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

Comments

2
votes

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]
community wiki

Comments

2
votes

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.)

2 Comments

127 chars: r=read();for(i=1;i<r*2;scale=6){n=sqrt(2*ir-ii);scale=0;n=1+n/1*2;i+=2;j=r-n/2;t+=2*n;while(j--)" ";while(n--)"*";" "};t/r/r
The only problem here is that it now fails for 0, but according to current rules, it's ok.
2
votes

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>');

Comments

1
vote

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);
 }
}
community wiki

1 Comment

Could probably save ~50 characters rewriting this in scala
1
vote

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}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.