Code Golf - π Tag


95

Die Herausforderung

Richtlinien für Code-Golf auf SO

Der kürzeste Code nach Zeichenanzahl, um eine Darstellung eines Radiuskreises unter RVerwendung des *Zeichens anzuzeigen , gefolgt von einer Approximation von π.

Die Eingabe ist eine einzelne Zahl R.

Da die meisten Computer ein Verhältnis von fast 2: 1 zu haben scheinen, sollten Sie nur Zeilen ausgeben, die yungerade sind. Dies bedeutet, dass RSie , wenn es ungerade ist, R-1Zeilen drucken sollten . Es gibt einen neuen Testfall R=13zur Verdeutlichung.

z.B.

Input
    5
Output      Correct                          Incorrect

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

Bearbeiten: Aufgrund der weit verbreiteten Verwirrung durch ungerade Werte von Rwerden alle Lösungen akzeptiert, die die unten angegebenen 4 Testfälle bestehen

Die Annäherung von π wird durch Teilen der doppelten Anzahl von *Zeichen durch gegeben .
Die Annäherung sollte auf mindestens 6 signifikante Stellen korrekt sein.
Führende oder nachgestellte Nullen sind zulässig, so beispielsweise einer 3, 3.000000, 003wird angenommen , für die Eingänge 2und 4.

Die Codeanzahl umfasst die Eingabe / Ausgabe (dh das vollständige Programm).

Testfälle

Input
    2
Output
     *** 
     *** 
    3.0

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

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

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

Bonus Testfall

Input
    13
Output

           *************       
        *******************    
       *********************   
      ***********************  
     ************************* 
     ************************* 
     ************************* 
     ************************* 
      ***********************  
       *********************   
        *******************    
           *************                                          
    2.98224852071

Möglicherweise möchten Sie klären, ob sich die "Eingabe" in der Befehlszeile oder in stdin befindet.
Greg Hewgill

1
@ Greg Hewgill, Fühlen Sie sich frei zu wählen, welche für die Sprache, die Sie verwenden, am bequemsten ist :)
John La Rooy

@ Greg Hewgill, Einige (dh nur sehr wenige) Programmiersprachenimplementierungen haben keinen Begriff von "Befehlszeile".
Joey Adams

1
Ich stelle fest, dass nur wenige der Antworten der Regel folgen, nur Zeilen zu setzen, in denen y ungerade ist. Bei einem ungeraden Wert von r (in den Testfällen nicht gezeigt) geben die meisten Zeilen aus, bei denen y gerade ist!
MtnViewMark

6
Regelmissbrauchsherausforderung: Erstellen Sie Code, der kürzer als der Code anderer ist, indem Sie nur die 4 erforderlichen Testfälle unterstützen.
Brian

Antworten:


15

In dc: 88 und 93 93 94 96 102 105 129 138 141 Zeichen

Nur für den Fall, ich verwende derzeit OpenBSD und einige angeblich nicht tragbare Erweiterungen.

93 Zeichen. Dies basiert auf der gleichen Formel wie die FORTRAN-Lösung (geringfügig andere Ergebnisse als Testfälle). Berechnet X ^ 2 = R ^ 2-Y ^ 2 für jedes Y.

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

88 Zeichen. Iterative Lösung. Entspricht Testfällen. Prüft für jedes X und Y, ob X ^ 2 + Y ^ 2 <= R ^ 2 ist

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

Laufen dc pi.dc.

Hier ist eine ältere kommentierte 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

1
Funktioniert nicht mit Linux DC, aber ich kann bestätigen, dass es unter OpenBSD funktioniert . Genial!
John La Rooy

@ Carlos, ja der (Betreiber ist sicher praktisch. Schade, dass es im DC, das mit Linux geliefert wird, nicht implementiert ist
John La Rooy

@gnibbler - "Eine vollständige Neufassung des Befehls dc unter Verwendung der bn (3) -Routinen mit großen Zahlen wurde erstmals in OpenBSD 3.5 veröffentlicht." Das wusste ich nicht. Einige nette neue Operatoren sind enthalten, aber sie sind als "nicht tragbare Erweiterungen" gekennzeichnet.
Carlos Gutiérrez

Ja, der (Betreiber allein darf 6 Schläge abwerfen!
Dan Andreatta

119

C: 131 Zeichen

(Basierend auf der C ++ - Lösung von 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);}

(Ändern Sie das i|=-nin i-=n, um die Unterstützung von Fällen mit ungeraden Zahlen zu entfernen. Dadurch wird lediglich die Anzahl der Zeichen auf 130 reduziert.)

Als Kreis:

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

1
Mir gefällt, wie Sie dem Code Kreise hinzugefügt haben, um ihn in einen Kreis zu verwandeln. Wäre +000 vorzuziehen?
Potatoswatter


1
wäre das nicht nur ein Charakter ...?
Ponkadoodle

1
Wie nimmt main()man vier intArgumente?
David R Tribble

2
@Load: 5.1.2.2.1 / 1: Die beim Programmstart aufgerufene Funktion wird benannt main. Es muss definiert werden… oder auf eine andere implementierungsdefinierte Weise . Das liegt daran, dass die Implementierung dieses Formular akzeptieren kann.
Kennytm

46

XSLT 1.0

Nur zum Spaß, hier ist eine XSLT-Version. Nicht wirklich Code-Golf-Material, aber es löst das Problem auf eine seltsam funktionierende XSLT-Art :)

<?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>

Wenn Sie es testen möchten, speichern Sie es unter pi.xsltund öffnen Sie die folgende XML-Datei im IE:

<?xml version="1.0"?> 
<?xml-stylesheet href="pi.xslt" type="text/xsl" ?> 
<R> 
  10 
</R> 

42
meine <eyes> </eyes>! Die Brille, sie <do> nichts </ do>!
Jimmy

1
Dang! Ich fürchte, Sie haben vielleicht meine HyperCard-Lösung für die Einzigartigkeit geschlagen: D
Joey Adams

7
Ich kann nicht glauben, dass Sie "open ... IE"
gesagt haben

Heh, ja, damals hatten wir nur IE und XML mit XSLT war die Lösung für all unsere Probleme. Gute alte Zeit! :)
Danko Durbić

XSL Version 1.0 Wow, ich erinnere mich, dass ich mich auf Version 2 gefreut habe, aber als es herauskam, war ich bereits weitergezogen.
Gradbot

35

Perl, 95 96 99 106 109 110 119 Zeichen:

$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

(Die neue Zeile kann entfernt werden und dient nur zur Vermeidung einer Bildlaufleiste.)

Yay! Kreisversion!

    $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

Für die Uneingeweihten die lange 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;

6
Das ist mit Abstand der unlesbarste Code, den ich in meinem ganzen Leben gesehen habe
Chris Marisic

13
Ich denke, Sie haben APL damals noch nie gesehen.
Peter Wone

5
@ Chris Marisic: Hast du die anderen getaggten Fragen / Themen überprüft code-golf? :) Ich habe viel mehr unlesbare Beispiele gesehen.
BalusC

3
@ Peter: Im Gegensatz zu den meisten anderen habe ich APL gesehen und geschrieben. Es dauert ein paar Wochen, um sich an die Sonderzeichen zu gewöhnen, aber danach kann es gut lesbar sein. Selbst nach ein paar Jahrzehnten, um sich daran zu gewöhnen, ist Perl immer noch viel schlimmer.
Jerry Coffin

1
111 Zeichen,$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

25

FORTRAN - 101 Zeichen

$ 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

Warten Sie, ich dachte, Formatierung war in Fortran wichtig? Sie haben Buchstaben in Spalte 1!
Joel

Die meisten Leute sitzen nach dem, was ich gesehen habe, immer noch auf Fortan77 fest.
Joel

8
Mir gefällt, wie die Kreisversion wie der Todesstern aussieht.
mskfisher

22

x86-Maschinencode: 127 Byte

Intel Assembler: 490 Zeichen

    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

Diese Version behandelt auch den Bonus-Testfall und umfasst 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

12
Ich liebe StackOverflow!
Zengr

2
Es ist interessant, dass einige der Hochsprachen kürzere Zeichenzahlen aufweisen als die dadurch erzeugte Binärdatei.
Colin Valliant

3
@Alcari: Wenn Sie den gesamten Code in die Bibliotheken der übergeordneten Sprachen aufnehmen würden, wäre deren Zeichenanzahl erheblich höher. In Assembler ist das Tun printf("%f",a/b)nicht trivial, es gibt keine einzige Anweisung, um dies zu tun, und meine obige Implementierung geht davon aus, dass 0 <= a / b <10 und dass die Operation eine Division ist und dass a und b ganze Zahlen sind.
Skizz

19

Python: 101 104 107 110 Zeichen

Basierend auf der anderen Python-Version von 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

Dank an AlcariTheMad für einen Teil der Mathematik.


Ah, die ungeraden sind mit Null als Mitte indiziert, erklärt alles.

Bonus Python: 115 Zeichen (schnell zusammen gehackt)

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

Wow, ja, '+' schlägt -1 und jeden Tag. Noch eine andere Technik, die ich aus meinem Kopf verdrängt habe, weil es fast nie das Richtige ist :-)
Nicholas Riley

Ich habe in der Vergangenheit C verwendet und Python noch nie angeschaut. Diese 104 Zeichen sind besser lesbar als das obige C ++. Tolle. Vielleicht sollte ich Python lernen ...
Dean Rather

@ Dean: Eines der Hauptziele von Python ist es, einfach zu lesen und zu schreiben.
Colin Valliant

Haben Sie darüber nachgedacht, exec auch mit Ihrer 104-Zeichen-Antwort zu verwenden? :)
John La Rooy

Ich müsste meine eigene Komprimierung ausführen - zlib, Marshalling usw. waren alle größer als der eigentliche Code.
Lunixbochs

12

Power Shell, 119 113 109 Zeichen

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

und hier ist eine schönere 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

@Thor: Ich hoffe nicht, aber das muss das hässlichste sein, was ich je geschrieben habe :)
Danko Durbić

3
Danke für diese schönere Version =)
Thor Hovden

10

HyperTalk: 237 Zeichen

Einrückung ist weder erforderlich noch gezählt. Es wird zur Klarheit hinzugefügt. Beachten Sie auch, dass HyperCard 2.2 die von mir verwendeten relationalen Nicht-ASCII-Operatoren akzeptiert.

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

Da HyperCard 2.2 stdin / stdout nicht unterstützt, wird stattdessen eine Funktion bereitgestellt.


1
Hypercard, Mr. Adams? Ernsthaft? Das ist sehr unerwartet.
Kawa

1
@Kawa: Deshalb habe ich es gepostet :) Außerdem ist Code Golf eine gute Möglichkeit, eine Testsuite aufzubauen, falls ich mich entscheide, in Zukunft einen HyperTalk-Interpreter zu schreiben.
Joey Adams

Hah! Ich würde das gerne sehen, XD
Kawa

Wenn Sie sich jemals dazu entschließen, diesen Dolmetscher zu schreiben, oder sich an einem bestehenden Dolmetscher beteiligen möchten, lassen Sie es mich wissen, und ich kann ihn auf hypercard.org erwähnen, und ich wäre gespannt, wie es geht :-)
uliwitness

10

C #: 209 202 201 Zeichen:

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

Nicht minimiert:

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

Ich kenne C # nicht sehr gut, aber sollten Sie nicht in der Lage sein, string[]aund 1-r(anstelle von -1+r)?
Kennytm

@ Kenny: Du hast recht. :) Das spart drei Zeichen, und dann habe ich es geschafft, fünf weitere loszuwerden.
Guffa

-r+1Ich habe das erste gesehen, was ich total vermisst habe.
Dykam

4
Auch entdeckt x*xx+++y*y, aber es ist eine verrückte Sache, auf den ersten Blick zu sezieren.
Dykam

Ich habe mir erlaubt, ein weiteres Byte zu entfernen ;-)
Joey

10

Haskell 139 145 147 150 230 Zeichen:

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

Umgang mit ungeraden Zahlen: 148 Zeichen:

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 Zeichen: (Basierend auf der 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 Zeichen:

main = do {r <-read`fmap`getLine; let {p = putStr; d = 2 / fromIntegral r ^ 2; lyn = let cmx = wenn x> r, dann p "\ n" >> gib m else zurück, wenn x * x + y * y <r * r dann p "*" >> c (m + d) (x + 1) sonst p "" >> cm (x + 1) in wenn y> r dann n sonst cn drucken (-r) >> = l (y + 2)}; l (1-r`mod`2-r) 0}

Nicht minimiert:

main = do r <- lies `fmap` getLine
          sei p = putStr
              d = 2 / fromIntegral r ^ 2
              lyn = lass cmx = wenn x> r
                                  dann p "\ n" >> return m
                                  sonst wenn x * x + y * y <r * r
                                       dann p * >> c (m + d) (x + 1)
                                       sonst p >> cm (x + 1)
                      in wenn y> r
                         dann drucke n
                         sonst cn (-r) >> = l (y + 2)
          l (1-r`mod`2-r) 0

Ich hatte gehofft, dass es einige der imperativen Versionen schlagen würde, aber ich kann es an dieser Stelle nicht weiter komprimieren.


2 weitere abgeschnitten, indem das "d" entfernt und stattdessen 1 hinzugefügt und dann "2 * n / fromIntegral r ^ 2" gedruckt wurde
Steve

Rasierte 3 Charaktere mit ein paar Haskell-Tricks. Ich finde es toll, dass in Haskell oft keine Kosten für mehrere Zeilen (Zeilenumbruch vs. Semikolon) anfallen und daher unser Code-Golf im Allgemeinen lesbar ist!
MtnViewMark

Genau genommen funktioniert die 145-Zeichen-Version nur, wenn die Eingabe gerade ist. Aber so oder so sehr schön.
Steve

Verkürzte die E / A-Leitung. Es sollte immer noch möglich sein, ein paar weitere Zeichen zu speichern, indem die Funktionsdefs in einen main = do {... let {...} ...} -Block verschoben werden, denke ich.
Comingstorm

@comingstorm: Cool! Ich wusste nichts über readLn. Dies wird vielen Haskell Code-Golf helfen. @Steve: Ja, ich versuche immer noch herauszufinden, wie ich das am effizientesten beheben kann.
MtnViewMark

10

Ruby, 96 Zeichen

(basierend auf Guffas C # -Lösung):

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

Vielen Dank! Es ist mir peinlich zu sehen, wie unlesbar Ruby sein kann ... :)
Mladen Jablanović

Sie können auch p sanstelle von puts s:)
John La Rooy

1
Schöne frische Ideen - ich mag es, dass Sie g mit 2 verschiedenen Schrittgrößen und dem <=> verwenden, um zu vermeiden, dass Code von logisch konvertiert werden muss
John La Rooy

9

PHP: 117

Basierend auf 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;

8

Ihr denkt viel zu viel nach.

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

8
Die Anzahl der Charaktere gerät etwas außer Kontrolle, meinst du nicht auch? :)
John La Rooy

7
Skaliert nicht. Nicht wartbar!
Spoulson

Ich habe versucht, den Testfall-Cheat so weit wie möglich zu komprimieren, und er war immer noch etwas größer als meine eigentliche Lösung: P
lunixbochs

5
+1, immer das offensichtlichste zuerst tun ... wenn es jemandem nicht gefällt, beschweren Sie sich lautstark, dass die Spezifikation nicht klar genug war
Mizipzor

Brian hatte einen halb-ernsthaften Versuch, die Testfälle speziell zu behandeln. Sie sollten auch seine positiv bewerten, wenn Ihnen diese Antwort gefällt;) stackoverflow.com/questions/2457995
John La Rooy

7

J: 47 , 46 , 45

Gleiche Grundidee wie bei anderen Lösungen, dh r ^ 2 <= x ^ 2 + y ^ 2 , aber die Array-orientierte Notation von J vereinfacht den Ausdruck:

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

Du würdest es so nennen c 2 oder c 8oder c 10usw. nennen.

Bonus: 49

Um beispielsweise ungerade Eingaben zu verarbeiten, 13müssen wir nach ungeradzahligen x-Koordinaten filtern, anstatt einfach jede zweite Ausgabezeile zu verwenden (da die Indizes jetzt entweder bei einer geraden oder einer ungeraden Zahl beginnen können). Diese Verallgemeinerung kostet uns 4 Zeichen:

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

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

Verbesserungen und Verallgemeinerungen aufgrund von Marshall Lochbam in den J-Foren .


5

Python: 118 Zeichen

So ziemlich ein unkomplizierter Port der 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

Für Python2 können Sie einfach verwendenr=input()
John La Rooy

Sie brauchen nicht den Raum zwischen printund' '
John La Rooy

OK, das ist beängstigend, es ist jetzt kürzer als die Perl-Version. (Ich habe "Input" komplett aus meinem Kopf verbannt, weil es normalerweise so unsicher ist ...)
Nicholas Riley

4

C ++: 169 Zeichen

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

Nicht minimiert:

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

(Ja, mit std :: anstelle von using namespace std weniger Zeichen zu verwenden)

Die Ausgabe hier stimmt nicht mit den Testfällen im ursprünglichen Beitrag überein, daher hier einer, der dies tut (aus Gründen der Lesbarkeit geschrieben). Betrachten Sie es als Referenzimplementierung (wenn Poita_ nichts dagegen hat):

#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 Zeichen (mit Ausgabe, die ich für richtig halte)

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

Der Code durchläuft eine Schleife von -n bis n, sodass bei einer Eingabe von beispielsweise 4 ein Durchmesser von 9 und nicht 7 angezeigt wird, wie in den Testfällen gezeigt.
Guffa

Ist es eine Anforderung, dass Ihr Kreis genau mit den OPs übereinstimmt ?
Peter Alexander

3
Möglicherweise möchten Sie es ändern, um #include <iostream.h>die #include <iostream> -- using namespace std;Kompatibilität mit alten C ++ - Compilern zu gewährleisten.
Earlz

1
@ Carlos, ich habe dieses bestimmte Bit nicht geschrieben, aber es ist ein binärer UND-Operator. Es wird überprüft, ob das letzte Bit gesetzt ist, was dem Ausführen entspricht i%2, aber "schneller" ist. Es ist nicht wirklich schneller, weil der Compiler es sowieso tun würde.
Peter Alexander

1
@Poita_: Tatsächlich verhalten sich i% 2 und i & 1 bei negativen Zahlen unterschiedlich. (-1) & 1 ist 1, was wir hier wollen. (-1)% 2 ist -1 auf meinem System, und dies entspricht C99. Obwohl if (i & 1) und if (i% 2) dasselbe tun, muss man mit if (i% 2 == 1) vorsichtig sein, was nicht funktioniert, wenn i negativ ist.
Joey Adams

3

PHP: 126 132 138

(basierend auf der Guffa C # -Lösung)

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;

Aktuell voll:

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;

Kann zuerst ohne @vorher sein, $saber nur wenn error_reporting auf 0 gesetzt ist (Hinweisausgaben verwirren den Kreis)


Was macht das / $ r in echo $ s * 2 / $ r / $ r;
Davidosomething

OHH Division ... der Abstand warf mich ab, dachte, es wäre eine Operator-Abkürzung, die ich noch nie gesehen hatte
Davidosomething

3

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

Laufen Sie mit $ ruby -p piday


Schön, aber es druckt nicht die Pi-Annäherung aus
John La Rooy

In 1.9.1 funktioniert dies nicht und es werden doppelte Anführungszeichen um den Kreis gedruckt.
Mladen Jablanović

Es ist normal, dass Golfprogramme nicht auf einem völlig anderen Sprachniveau arbeiten. Wie viele Perl- oder Python-CGs arbeiten mit jeder Version der Sprache? Es stellt sich jedoch interessant heraus, dass der Grund dafür ist, dass Integer|Floatder Float auf 1.9 nicht mehr erzwungen wird.
DigitalRoss

3

APL: 59

Diese Funktion akzeptiert eine Nummer und gibt die beiden erwarteten Elemente zurück. Funktioniert in Bonusfällen korrekt.

{⍪(⊂' *'[1+m]),q÷⍨2×+/,m←(2|v)⌿(q←⍵*2)>v∘.+v←2*⍨⍵-⍳1+2×⍵-1}

Der Dialekt ist Dyalog APL mit dem Standardindexursprung. Die Fähigkeitsstufe ist ein ahnungsloser Neuling . Wenn also ein APL-Guru sie auf 10 Charaktere reduzieren möchte, sei mein Gast!


Sie können es online unter Try APL ausprobieren. Fügen Sie es einfach ein und geben Sie eine Nummer danach ein:

   {⍪(⊂' *'[1+m]),q÷⍨2×+/,m←(2|v)⌿(q←⍵*2)>v∘.+v←2*⍨⍵-⍳1+2×⍵-1} 13
      *************
   *******************
  *********************
 ***********************
*************************
*************************
*************************
*************************
 ***********************
  *********************
   *******************
      *************
2.98225

Obwohl ich APL nicht kenne, sieht es hübscher aus als die J-Version.
Ahala

@ahala In der Tat. APL ist sowohl konzeptionell als auch ästhetisch schön. Ich fing an, J zu lernen, wurde aber durch die zufällige ASCII-Verrücktheit ausgeschaltet. Eine gute Seele hat einen Open-Source-APL-Interpreter für Node.js (npm install apl) geschrieben, der ziemlich gut ist. Der obige Code wird mit nur einer geringfügigen Änderung berechnet (keine Monade , 2. Zeichen). Auf allen Anbieterseiten, z. B. Dyalog, finden Sie eine gute APL-Dokumentation.
Tobia

2

Und ein Bash-Eintrag: 181 186 190 Zeichen

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

Laufen Sie mit z bash py.sh 13


2

Python: 148 Zeichen.

Fehlgeschlagener (dh nicht kurz genug) Versuch, die Regeln zu missbrauchen und die Testfälle fest zu codieren, wie ich in der Antwort auf den ursprünglichen Beitrag erwähnt habe. Es könnte einfacher gewesen sein, es mit einer ausführlicheren Sprache zu missbrauchen:

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]

2

bc: 165 , 127 , 126 Zeichen

Basierend auf der 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

(Neue Zeile nach der letzten Zeile kann hier nicht weggelassen werden.)


1
127 Zeichen: r = read (); für (i = 1; i <r * 2; scale = 6) {n = sqrt (2 * i r-i i); scale = 0; n = 1 + n / 1 * 2 ; i + = 2; j = rn / 2; t + = 2 * n; while (j--) ""; while (n -) "*"; "}; t / r / r
Carlos Gutiérrez

Das einzige Problem hier ist, dass es jetzt für 0 fehlschlägt, aber nach den aktuellen Regeln ist es in Ordnung.
Przemoc

2

JavaScript (SpiderMonkey) - 118 Zeichen

Diese Version akzeptiert Eingaben von stdin und besteht die Bonus-Testfälle

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)

Verwendung: cat 10 | js thisfile.js - Die jsbin-Vorschau fügt einen Alias ​​für print / readline hinzu, damit Sie sie im Browser anzeigen können

Javascript: 213 163


Aktualisiert

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

Niemand sagte, es müsse im Browser korrekt gerendert werden - nur die Ausgabe. Als solches habe ich die Pre-Tags entfernt und weiter optimiert. Um die Ausgabe anzuzeigen, müssen Sie die generierte Quelle anzeigen oder Ihr Stylesheet entsprechend festlegen. Pi ist auf diese Weise weniger genau, aber es ist jetzt zu spezifizieren.


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

Nicht minimiert:

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

1

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

Nicht minimiert:

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

Könnte wahrscheinlich ~ 50 Zeichen sparen, die dies in scala
rwyland

1

GAWK: 136 , 132 , 126 , 125 Zeichen

Basierend auf der 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}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.